2013-09-25 133 views
6

Có thể sử dụng con trỏ hàm chung làm tham số mẫu không? Mẫu con trỏ hàm có thể chấp nhận các hàm miễn phí, hàm thành viên và hàm lambda. Để đơn giản, giả sử các chức năng chỉ có một tham số, nhưCách sử dụng con trỏ hàm chung làm tham số mẫu?

template<class ArgumentT, class ReturnT, function* f> 
struct A 
{ 
    // f is used somewhere. 
}; 
+0

Bạn có thể làm điều đó, nhưng bạn sẽ nhận được các loại không tương thích khác nhau cho các loại tức thời loại chức năng khác nhau. Tức là, bạn không thể gán một A với một con trỏ hàm tổng quát tới một hàm A có con trỏ đến hàm thành viên, ngay cả khi ArgumentT và ReturnT là giống nhau. – ComicSansMS

Trả lời

8

Mẫu tranh luận bình thường có thể tham khảo một hàm.

#include <iostream> 

template <class ArgT, class RetT, class F> 
struct A { 
    F f; 
public: 
    A(F f) : f(f) {} 

    RetT operator()(ArgT arg) { return f(arg); } 
}; 

int unchanged(int i) { return i; } 

int main(){ 
    A < int, int, int(*)(int)> t{ unchanged }; 

    for (int i = 0; i < 10; i++) 
     std::cout << t(i) << "\n"; 
} 

Không có gì hạn chế mẫu đối số để một hàm dù là - bạn có thể chỉ là một cách dễ dàng sử dụng một số lớp quá tải operator(), và gọi đó thay vì (và, trên thực tế, đó là thường thích hợp hơn).

0

Bạn đang kết hợp các loại và dữ liệu, bạn muốn một cái gì đó giống như:

template<class ArgumentT, class ReturnT, typename F*> 
struct A { 
    //use F* to refer to f somewhere 
}; 
+2

Ngữ pháp này có đúng không? – user1899020

0

Bạn có thể đạt được một cái gì đó gần gũi với:

template<class ArgumentT, class ReturnT, class F, F f> 
struct A; 

template<class ArgumentT, class ReturnT, ReturnT (*f)()> 
struct A<ArgumentT, ReturnT, ReturnT (*)(), f> 
{ 
    // f is used somewhere. 
}; 

template<class ArgumentT, class ReturnT, class C, ReturnT (C::*f)()> 
struct A<ArgumentT, ReturnT, ReturnT (C::*)(), f> 
{ 
    // f is used somewhere. 
}; 

... nhưng bạn không thể lấy một cái gì đó giống như một std::function<ReturnT()> như một tổ chức phi kiểu mẫu tham số. Chuyên môn cho các con trỏ hàm cũng sẽ chấp nhận các lambdas không bắt giữ.

2

tôi sẽ khuyên bạn nên sử dụng std :: chức năng <> nếu bạn có thể sử dụng C++ 11 hoặc tăng :: chức năng <> nếu bạn không thể:

template<class ArgumentT, class ReturnT > struct A { 
    typedef std::function< ReturnT(ArgumentT) > Function; 
    void foobar(Function f) { ReturnT ret = f(arg); } 
}; 

Trong trường hợp này bạn có thể vượt qua con trỏ hàm, functor, lambda, hoặc sử dụng std :: bind hoặc boost :: liên kết với hầu như bất kỳ hàm nào mà chữ ký không khớp. Tôi không chắc chắn bạn cần mẫu trong trường hợp này, bạn có thể sử dụng std :: chức năng trực tiếp, nhưng điều đó phụ thuộc vào mã của bạn.

+2

Có nhiều nhược điểm khi sử dụng hàm std :: tuy nhiên, đây không phải là lời khuyên về chăn. – xaxxon