2012-03-15 111 views
5

我會知道是否有方法使用std :: mem_fun傳遞參數? 我想確切地說,我可以有儘可能多的參數和很多成員函數。
的問題是,我在一箇舊的標準,我在尋找一個完整的STL方式,以便提升是不允許的答案,即使我知道我能做到這一點很容易=/如何使用std :: mem_fun傳遞參數

這裏是一個小我想怎麼說明使用方法:

#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; 
} 

回答

11

通過std::bind1st使用std::bindstd::bind2nd

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

不幸的是,標準不利於這兩個參數的版本,你需要編寫自己:

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

std::bind1ststd::bind2nd。它們使用起來相當笨拙和醜陋,但如果你堅持只使用C++ 03中的內容而沒有任何補充,它們幾乎都可用。

編輯:當/如果我需要這樣做,我通常使用一個小的函子類而不是使用std::bind1st和/或std::bind2nd。這與最終產生的結果並不完全不同,但(IMO)通常更具可讀性。

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)); 

然而,我自己的看法是,大多數情況下這是一種創可貼。它經常使用for_each。我通常會發現,有一些想法,我可以找到一個更合適的算法,根本就不需要這個訂單上的任何東西。

+0

謝謝你的回答,你能舉個例子如何使用它 ?我無法得到它的工作.. – klefevre 2012-03-15 03:18:13

+0

我想我可以,但1)@LokiAstari已經有了,所以它不會增加太多,2)我從來沒有使用它們。我很久以前決定他們不值得這樣做。在我需要這種事情的(令人驚奇的)情況下,我寫了一個小的函子類來處理它。值得慶幸的是,在C++ 11中,也很容易消除這一點。 – 2012-03-15 03:22:36

+0

無論如何感謝.. – klefevre 2012-03-15 03:23:48

1

您可以通過綁定:

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

他的「舊標準」,即98或03.這是C++ 11。 – MSalters 2012-03-15 10:21:42

+0

@ MSalters:注意到,儘管如此,去年C++ 11是如此。 – 2012-03-15 10:25:29