2011-10-26 27 views
7

Tôi đang cố gắng để vượt qua một std :: chức năng thông qua một phương pháp như vậy:C++ 0x std :: chức năng như một đối số phương pháp

class dispatch 
{ 
    public: 
    deliver(std::function<void (void)> task); 
} 

này hoạt động như mong đợi. Tuy nhiên tôi muốn chuyển đối số cho một số phương thức được cung cấp dưới dạng tác vụ nhưng không muốn tạo quá tải cho tất cả các hàm khác nhau < ...>.

ví dụ là nó ở tất cả có thể chỉ là để tạo ra một phương pháp như sau

deliver(std::function& task); 

và chỉ gọi với

dispatch->deliver(bind(&Object::method, X)); 

hoặc

dispatch->deliver(bind(&Object::method, X, arg1, arg2)); 

vv ...

Cảm ơn cho mọi đầu vào. Nó sẽ xuất hiện lỗi thực sự của tôi là với các cuộc gọi để gửi-> cung cấp với các đối số bổ sung cũng là một cuộc gọi ràng buộc.

dispatch->deliver(bind(&Object::method1, X1, bind(&Object::method1, X2)); 

error: /usr/include/c++/v1/functional:1539:13: error: no matching function for call to '__mu_expand' return __mu_expand(__ti, __uj, __indices());

+0

Thiếu ';' sau khai báo lớp học. :-) –

Trả lời

9

std::function<void(void)> đã đa hình, đó là toàn bộ điểm của nó. Vì vậy, hai đoạn cuối cùng sẽ hoạt động (miễn là hàm functor bind trả về có thể được gọi không có đối số và không trả về gì, tất nhiên), mà không thay đổi những gì bạn đã có.

3

Có, có thể miễn là bạn sử dụng ràng buộc để tạo ra đối tượng chức năng tương thích:

#include <boost/bind.hpp> 
#include <boost/function.hpp> 
#include <iostream> 
#include <list> 
#include <string> 

typedef boost::function<void(void)> fun_t; 
typedef std::list<fun_t> funs_t; 

void foo() 
    { std::cout <<"\n"; } 
void bar(int p) 
    { std::cout<<"("<<p<<")\n"; } 
void goo(std::string const& p) 
    { std::cout<<"("<<p<<")\n"; } 

void caller(fun_t f) 
    { f(); } 

int main() 
{ 
    funs_t f; 
    f.push_front(boost::bind(foo)); 
    f.push_front(boost::bind(bar, int(17))); 
    f.push_front(boost::bind(goo, "I am goo")); 

    for (funs_t::iterator it = f.begin(); it != f.end(); ++it) 
    { 
     caller(*it); 
    } 

    return 0; 
} 

(Lưu ý, tôi sử dụng Boost.Function và Boost.Bind, nhưng không nên có sự khác biệt với việc sử dụng std :: bind và std :: function.)

+0

Tôi có nên chuyển 'fun_t' theo giá trị hoặc tham chiếu không? – hkBattousai

+0

@hkBattousai Nó phụ thuộc. Đọc http://stackoverflow.com/a/8711486/151641 và http://stackoverflow.com/a/18366273/151641 – mloskot

1
class dispatch 
{ 
    public: 
    template <typename ... Params> 
    deliver(std::function<void (Params && p...)> task, Params && p) 
    { 
     task(std::forward(p)...); 
    } 
}; 

Tôi chưa biên soạn (sửa đổi chào mừng!), nhưng ý tưởng sẽ hoạt động.

dispatch->deliver(bind(&Object::method, X)); 
dispatch->deliver(bind(&Object::method, X, arg1, arg2)); // OR! 
dispatch->deliver(bind(&Object::method, X), arg1, arg2); 

Điều tôi chưa rõ là cách hoạt động này nếu Object::method có thông số mặc định thay vì quá tải.

+0

+1: Một nitpick, Nó có thể hiệu quả hơn để vượt qua std :: function như tham chiếu const . – mirk

+0

@DirkM Bạn nói đúng, nhưng kể từ khi OP không làm điều đó, tôi đã chọn không làm như vậy. Anh ta có thể làm một cái gì đó trong phương thức cung cấp mà không liên quan đến "giao hàng". Tôi hy vọng là không. –

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