2014-11-18 32 views
6

Tôi có sau C++ 11 ví dụ nơi tôi có một hàm call có sử dụng các mẫu variadic để chấp nhận và gọi một phương thức lớp generic:không phù hợp khấu trừ gói thông số với các mẫu variadic

#include <utility> 

template <typename T, typename R, typename... Args> 
R call(R (T::*fn)(Args...), T *t, Args&&... args) { 
    return ((*t).*fn)(std::forward<Args>(args)...);  
} 

class Calculator { 
    public: 
    int add(const int& a, const int& b) { 
     return a + b; 
    } 
}; 

int main() { 
    Calculator *calculator = new Calculator(); 
    int* a = new int(2);  
    int* b = new int(4); 

    // compiles 
    int res1 = calculator->add(*a, *b);  

    // does not compile! 
    int res2 = call<Calculator>(&Calculator::add,calculator, *a, *b);  

    return 0; 
} 

Như nhận xét trong mã , Tôi không thể vượt qua một số int khi chức năng chấp nhận const int, trong khi đang thực hiện lệnh gọi phương thức có thể. Tôi nhận được lỗi biên dịch sau:

error: no matching function for call to ‘call(int (Calculator::*)(const int&, const int&), Calculator*&, int&, int&)’ 
    int res2 = call<Calculator>(&Calculator::add,calculator, *a, *b);  
                    ^

inconsistent parameter pack deduction with ‘const int&’ and ‘int&’ 
    int res2 = call<Calculator>(&Calculator::add,calculator, *a, *b);  
                    ^

Mẫu C++ variadic có thực thi kiểm tra chặt chẽ hơn khi so sánh với thực thi thông thường không? Tôi đang sử dụng g ++ 4.8.1 với C++ 11.

+0

Có thể bạn sẽ thích lỗi Clang của tốt hơn: * lưu ý: ứng cử viên mẫu phớt lờ: suy luận loại mâu thuẫn cho tham số 'args' ( so với ) * – chris

+0

Vậy điều đó có nghĩa là các loại phải khớp chính xác khi sử dụng các mẫu variadic? – jeffreyveon

+1

Điều đó có nghĩa là bạn không thể suy ra các loại khác nhau cho cùng một tham số mẫu vì trình biên dịch không thể biết bạn muốn gì. Bạn luôn có thể bỏ qua chức năng chụp rõ ràng và chỉ có tham số đối tượng có thể gọi: 'template cuộc gọi tự động (F f, T * t, Args && ... args) { trả lại (t -> * f) (std :: forward (args) ...); } ' – chris

Trả lời

11

Cách bạn đang gọi mẫu chức năng của bạn, các mẫu tham số gói Args sẽ được rút ra từ hai nguồn:

  • Các loại con trỏ thành viên chức năng - int (Calculator::*)(const int&, const int&)
  • các loại thực tế của các đối số (*a, *b) bạn thông qua cho các gói thông số chức năng - int &, int &

đối với khấu trừ để thành công, kết quả suy luận phải exac tly match. Họ rõ ràng là không.

Đây không phải là mới hoặc đặc biệt đối với các mẫu variadic. Bạn có cùng một vấn đề nếu bạn cố gắng làm std::max(1, 1.5) - trình biên dịch khấu trừ int từ một đối số, double từ khác và khấu trừ không thành công do hai xung đột.

đơn giản khắc phục có lẽ là chụp hai gói:

template <typename T, typename R, typename... Args1, typename... Args2> 
R call(R (T::*fn)(Args1...), T *t, Args2&&... args) { 
    return ((*t).*fn)(std::forward<Args2>(args)...);  
} 
+0

Tất nhiên :) Cảm ơn. – jeffreyveon

Các vấn đề liên quan