2009-06-02 33 views
13

xem xét mã đơn giản và vô nghĩa này.C++ functor và các mẫu chức năng

#include <iostream> 

struct A { 
    template<int N> 
    void test() { 
     std::cout << N << std::endl; 
    } 
}; 

int main() { 
    A a; 
    a.test<1>(); 
} 

Đây là ví dụ rất đơn giản về mẫu chức năng. Điều gì sẽ xảy ra nếu tôi muốn thay thế A::test với quá tải operator() để biến nó thành một hàm functor?

#include <iostream> 

struct A { 
    template<int N> 
    void operator()() { 
     std::cout << N << std::endl; 
    } 
}; 

int main() { 
    A a; 
    a<1>(); // <-- error, how do I do this? 
} 

Chắc chắn nếu tham số operator() lấy tham số phụ thuộc vào mẫu, trình biên dịch có thể suy ra mẫu. Nhưng tôi chỉ không thể tìm ra cú pháp thích hợp để xác định các tham số mẫu với một hàm functor không tham số.

Có cách nào phù hợp để thực hiện việc này không?

Rõ ràng, mã này sẽ làm việc kể từ khi nó đi qua các cú pháp functor:

a.operator()<1>(); 

nhưng mà kinda đánh bại mục đích của nó là một :-P functor.

+0

+1: Cú pháp lạ để sử dụng trong mã-obfuscation. Nên được đề cập trong http://thc.org/root/phun/unmaintain.html :-) –

Trả lời

9

Không có nhau "trực tiếp" Con đường tôi biết khác hơn:

a.operator()<1>(); 

cú pháp. Nếu bạn đang mở để thay đổi mã, di chuyển tham số mẫu đến lớp sẽ hoạt động hoặc sử dụng một liên kết (boost | tr1) :: để tạo một đối tượng hàm (boost | tr1) ::.

24

Bạn chỉ có thể gọi

a.operator()<1>(); 

nhưng điều đó sẽ không được sử dụng một functor. Functors cần một toán tử non template(), vì chúng phải có thể được gọi là varname() và điều đó sẽ không hoạt động với mã của bạn.

Để làm cho nó một functor thực thay đổi mã của bạn một lớp mẫu (functors là lớp):

#include <iostream> 

template<int N> 
struct A { 
    void operator()() { 
     std::cout << N << std::endl; 
    } 
}; 

int main() { 
    A<1> a; 
    a(); 
} 
2

Bạn đang cố gắng để vượt qua một tham số mẫu để một thể hiện của một đối tượng, mà như xa như tôi biết không được phép. Bạn chỉ có thể chuyển các tham số mẫu tới các hàm mẫu hoặc các đối tượng mẫu.

a.test < 1>(); và a.operator() < 1>(); làm việc vì chúng đang phục vụ như các hàm mẫu.

Sử dụng tăng :: liên kết (xem thư viện tăng cường) để khắc phục.

struct A { 
    void operator()(int n) { 
     std::cout << n << std::endl; 
    } 
}; 

int main(int argc, char* argv[]) { 
    A a; 
    boost::function<void()> f = boost::bind<void>(a, 1); 
    f(); // prints 1 

    return 0; 
} 

Và bạn thậm chí không phải gây rối với mẫu!

0

Không, không có cách nào xung quanh nó. Như bạn đã nói, bạn phải gọi cho toán tử một cách rõ ràng (mà đánh bại mục đích), hoặc các đối số mẫu phải có khả năng được trình biên dịch suy ra.

1

Bạn đang mắc kẹt. Bạn đã xem xét một cái gì đó như là

struct A { 
    template<int N> 
    struct B 
    { 
     void operator()() 
     { std::cout << N << std::endl; } 
    }; 

    template<int N> 
    B<N> functor() {return B<N>();} 
}; 

int main() 
{ 
    A a; 
    a.functor<1>()(); 
} 
Các vấn đề liên quan