2012-05-15 22 views
5

Tôi chỉ thấy mình tạo ra một lớpTôi có đang phát minh lại bánh xe với lớp chuyển tiếp cuộc gọi phương thức tầm thường này không?

template <typename T> struct invoker { 
    void operator()(T& it) const {it();} 
}; 

để tôi có thể vượt qua một invoker<foo> một cái gì đó (mà không phải là dưới sự kiểm soát của tôi) có nhu cầu gọi invoker<foo>::operator()(foo&) vào nó nhiều lần với foo trường hợp khác nhau, để làm cho nó chuyển tiếp các cuộc gọi đó đến phương thức foo::operator()() của foo.

Tôi biết nó chỉ là một vài dòng, nhưng điều này có vẻ như là loại điều mà có thể đã được cung cấp bởi chức năng của STL, hoặc boost::bind bằng cách nào đó. Ngoại trừ tôi không thể nhìn thấy lừa, nếu có một. (Tôi chắc chắn rằng tôi không phải là người đầu tiên sử dụng một cái gì đó rất như thế này; nó có một cái tên?)

+1

tôi nghĩ rằng C++ 11 có thứ gì đó cho điều này quá – pyCthon

+1

Hiện tại tôi đang ở trên g ++ 4.4.5; Tôi không nghĩ rằng g ++ có lambdas cho đến khi 4,5. Tò mò để xem một giải pháp lambda nếu một trong những được đăng mặc dù; Tôi có thể sống với lớp invoker của tôi cho đến khi nâng cấp phiên bản g ++. – timday

+0

Tại sao bạn không gọi 'foo :: operator() 'trực tiếp? Tôi có nghĩa là, các lớp mà gọi là 'invoker :: operator() 'đã làm một cái gì đó như' some_invoker (some_foo); ', trong khi bạn chỉ có thể gọi nó như thế này:' some_foo(); '. Bạn đang thêm một lớp không cần thiết của indirection. – mfontanini

Trả lời

5

Vâng, bạn đang phát minh lại bánh xe. std :: mem_fun_ref làm những gì bạn muốn.

std::vector<foo> foos; 

... 

std::for_each(foos.begin(), foos.end(), std::mem_fun_ref(&foo::operator())); 

Hoặc:

std::vector<foo*> foos; 

... 

std::for_each(foos.begin(), foos.end(), std::mem_fun(&foo::operator())); 

Không cần phải gây rối với liệu param của bạn là ptr hay không là một lợi ích lớn của boost :: mem_fn.

Bất cứ điều gì phức tạp hơn nhiều so với điều đó mặc dù và bạn bắt đầu gặp rắc rối với các chất kết dính C++ 03 và cần một cái gì đó biểu cảm hơn như boost.bind.

+4

Chỉ muốn chỉ ra 'std :: mem_fun' và' std :: mem_fun_ref' không được dùng cho 'std :: mem_fn' trong C++ 11. –

6

Vâng, bạn có thể sử dụng std::bind, có lẽ boost::bind cũng như để đạt được các hành vi tương tự:

#include <string> 
#include <iostream> 
#include <functional> 

struct foo { 
    void operator()() { 
     std::cout << "Hallo, im at addr: " << std::hex << this << std::endl; 
    } 
}; 

int main() { 
    std::function<void(foo*)> fun = std::bind(&foo::operator(), std::placeholders::_1); 
    foo f1, f2; 
    fun(&f1); 
    fun(&f2); 
} 

Đầu ra:

Hallo, im at addr: 0xbffc396a 
Hallo, im at addr: 0xbffc3969 

Nếu bạn sử dụng một lớp mẫu cho các loại đối số, bạn có thể có behvaiour cùng mà không reinventing the wheel.

Sửa: như điên Eddie chỉ ra, bạn chỉ có thể sử dụng boost::mem_fn hoặc std::mem_fn:

std::function<void(foo*)> fun = std::mem_fn(&foo::operator()); 

Thay vì bind.

+1

Bạn thực sự không cần phải ràng buộc ở đây và nó có thể là đáng giá để bỏ qua nó. Bind phải đi qua một hệ thống chuyển đổi đối số để hợp nhất hai danh sách đối số và gọi mục tiêu có thể gọi được. boost :: mem_fn sẽ thực hiện thủ thuật và thực sự bind() cho các con trỏ thành viên sử dụng nó. –

+0

@CrazyEddie đẹp, tôi đã sử dụng 'mem_fn' một thời gian trước đây, nhưng hoàn toàn quên mất nó. Editted câu trả lời của tôi: D – mfontanini

+0

OK điều này là chính xác loại điều tôi đang tìm kiếm cảm ơn; Rõ ràng là khi bạn nhìn thấy nó, có lẽ tôi đã thuyết phục bản thân mình (quá trễ ở đây) rằng bởi vì phương pháp foo mà tôi quan tâm không có tranh cãi, không có vai trò gì cho một người giữ chỗ _1 ... quá sai. – timday

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