簡體   English   中英

如何使用 std::mem_fun 傳遞參數

[英]How passing arguments using std::mem_fun

我想知道是否有辦法使用 std::mem_fun 傳遞參數? 我想確切地說,我可以擁有盡可能多的參數和許多成員函數。
問題是我采用的是舊標准,我正在尋找一種完整的 stl 方式,因此即使我知道我可以輕松做到,也不允許使用 boost 作為答案 =/

這是我想如何使用它的一個小說明:

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

通過std::bind1ststd::bind2nd使用std::bind

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

Lambda 版本

最初的答案是在 2012 年,當時 Lambda 剛剛被添加到標准中,並且很少有編譯器符合 C++11。 現在 8 年后,大多數編譯器都符合 C++11,我們可以使用它使這些事情變得更簡單。

// Binding 1 parameter
std::for_each(list.begin(), list.end(),
              [](auto act){act->do_something(1);})

// Binding 2 parameters
std::for_each(list.begin(), list.end(),
              [](auto act){act->do_func(1, 2);})

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發生。 我通常會發現,經過一些思考,我可以找到更合適的算法,該算法通常完全不需要此訂單上的任何內容。

您可以通過綁定:

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

c++20 ,您不需要std::bind和 family。 您可以使用std::mem_fn這樣做。 請注意std::mem_func++20不可用

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

struct Foo {
    void display_number(int i, char ch, std::string s) {
        std::cout << "number: " << i << " character: " << ch << " string: " << s << '\n';
    }
};

int main() {
    Foo f;

    auto print_num = std::mem_fn(&Foo::display_number);
    print_num(f, 42, 'a', "Hello!");
}

輸出 :

number: 42 character: a string: Hello!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM