2012-03-15 45 views
5

Tôi sẽ biết nếu có một cách để vượt qua đối số bằng cách sử dụng std :: mem_fun? Tôi muốn chính xác rằng tôi có thể có nhiều đối số nhất có thể và rất nhiều chức năng của thành viên.
Vấn đề là tôi đang ở trên một tiêu chuẩn cũ và tôi đang tìm kiếm một cách thức đầy đủ để không được phép trả lời ngay cả khi tôi biết tôi có thể làm điều đó dễ dàng =/Làm thế nào để vượt qua các đối số bằng cách sử dụng std :: mem_fun

Đây là một chút minh họa làm thế nào tôi muốn sử dụng nó:

#include <list> 
#include <algorithm> 

// Class declaration 
// 
struct Interface { 
    virtual void run() = 0; 
    virtual void do_something(int) = 0; 
    virtual void do_func(int, int) = 0; 
}; 

struct A : public Interface { 
    void run() { cout << "Class A : run" << endl; } 
    void do_something(int foo) { cout << "Class A : " << foo << endl; } 
    void do_func(int foo, int bar) { cout << "Class A : " << foo << " " << bar << endl; } 
}; 

struct B : public Interface { 
    void run() { cout << "Class B : run" << endl; } 
    void do_something(int foo) { cout << "Class B : " << foo << endl; } 
    void do_func(int foo, int bar) { cout << "Class B : " << foo << " " << bar << endl; } 
}; 

// Main 
// 
int main() { 
    // Create A and B 
    A a; 
    B b; 

    // Insert it inside a list 
    std::list<Interface *> list; 
    list.push_back(&a); 
    list.push_back(&b); 

    // This works 
    std::for_each(list.begin(), list.end(), std::mem_fun(&Interface::run)); 

    // But how to give arguments for those member funcs ? 
    std::for_each(list.begin(), list.end(), std::mem_fun(&Interface::do_something)); 
    std::for_each(list.begin(), list.end(), std::mem_fun(&Interface::do_func)); 
    return 0; 
} 

Trả lời

11

Sử dụng std::bind qua std::bind1ststd::bind2nd

std::for_each(list.begin(), list.end(), 
       std::bind2nd(std::mem_fun(&Interface::do_something),1) // because 1st is this 
      ); 

Thật không may, tiêu chuẩn không giúp cho phiên bản hai đối số và bạn cần phải viết riêng của bạn:

struct MyFunctor 
{ 
    void (Interface::*func)(int,int); 
    int   a; 
    int   b; 

    MyFunctor(void (Interface::*f)(int,int), int a, int b): func(f), a(a), b(b) {} 

    void operator()(Interface* i){ (i->*func)(a,b);} 
}; 

std::for_each(list.begin(), list.end(), 
       MyFunctor(&Interface::do_func, 1, 2) 
      ); 
1

Xem std::bind1ststd::bind2nd. Chúng khá vụng về và xấu xí để sử dụng, nhưng nếu bạn khăng khăng chỉ sử dụng những gì có mặt trong C++ 03 mà không có bất kỳ bổ sung nào, chúng có khá nhiều thứ sẵn có.

Chỉnh sửa: khi/nếu tôi cần làm điều này, tôi thường làm điều đó với một lớp nhỏ functor thay vì sử dụng std::bind1st và/hoặc std::bind2nd. Điều này không phải là cuối cùng nhiều khác với những gì tạo ra, nhưng (IMO) nó thường dễ đọc hơn.

template<class T> 
class invoke_do_something { 
    int value; 
public: 
    adder(int x) : value(x) {} 
    void operator()(T &t) { 
     t.do_something(value); 
    } 
}; 

std::for_each(list.begin(), list.end(), invoke_do_something(1)); 

Theo tôi, phần lớn thời gian này là loại trợ giúp. Nó xảy ra liên tục sử dụng for_each. Tôi thường thấy rằng với một số suy nghĩ, tôi có thể tìm thấy một thuật toán phù hợp hơn, mà thường xuyên loại bỏ sự cần thiết cho bất cứ điều gì về thứ tự này cả.

+0

Cảm ơn bạn đã trả lời, bạn có thể đặt ví dụ về Làm thế nào để sử dụng nó ? Tôi không thể làm cho nó hoạt động .. – klefevre

+0

Tôi cho rằng tôi có thể, nhưng 1) @LokiAstari đã có, vì vậy nó sẽ không thêm nhiều, và 2) Tôi không bao giờ sử dụng chúng bản thân mình. Tôi đã quyết định từ lâu họ không đáng để gặp rắc rối. Trong tình huống (hiếm khi đáng ngạc nhiên), nơi tôi cần loại điều đó, tôi viết một lớp nhỏ để giải quyết nó. Rất may, trong C++ 11, thật dễ dàng để loại bỏ điều đó. –

+0

Thanks anyway .. – klefevre

1

Bạn có thể bằng cách liên kết:

using std::placeholders::_1 
int a; 
std::for_each(list.begin(), list.end(), std::bind(&Interface::do_something, _1, a)); 
+2

Anh ấy đang ở trên "tiêu chuẩn cũ", tức là 98 hoặc 03. Đây là C++ 11. – MSalters

+0

@MSalters: nhận thấy rằng, mặc dù, C++ 11 là sooooo năm ngoái. –

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