将类成员函数传递给for_each

时间:2017-05-09 21:09:49

标签: class c++11 for-loop foreach

我的问题是:如何将类成员函数传递给for_each

代码我正在努力工作:(当在课堂外定义函数时起作用)

失败的部分被注释掉 - 使用带有函数的for_each作为类成员函数

有关如何使其发挥作用的任何建议吗?

#include <iostream>
#include <algorithm>
#include <vector>

void my_function(std::string str)
{
std::cout << "processing settings: " << str << std::endl;
}

class Settings_vector{

public:
std::vector <std::string> settings;

Settings_vector(){                          // push back vector of objects
    settings.push_back("settings 1");
    settings.push_back("settings 2");
    settings.push_back("settings 3");
    settings.push_back("settings 4");
                 }

void tester(std::string settings_string){
    std::cout << "processing settings: " << settings_string << std::endl;
                                        }
};

int main()
{
//std::vector<std::string> my_vector;

Settings_vector settings_vector;

    std:: cout << "doing things the non-class way\n" << std::endl;
for_each(settings_vector.settings.begin(), settings_vector.settings.end(),     my_function); // testing function
// WORKS
/*
  std:: cout << "doing things the modern way\n" << std::endl;
for_each(settings_vector.settings.begin(), settings_vector.settings.end(),    settings_vector.tester); // testing function
// FAILS
*/

std:: cout << "doing things the oldskool way\n" << std::endl;
for (int i = 0;i<settings_vector.settings.size();++i) {
settings_vector.tester(settings_vector.settings[i]);
}
// WORKS


return 0;
}

2 个答案:

答案 0 :(得分:6)

最简单的方法是使用lambda表达式。更复杂的方法是使用std::bind()绑定所有已知参数(此处为类成员函数的实例),并将未知参数与占位符_1_2等保留在一起。

#include <iostream>
#include <algorithm>
#include <vector>

class Settings_vector
{
  Settings_vector()
    : settings { "settings 1"
               , "settings 2"
               , "settings 3"
               , "settings 4"
               }
  {}

  void tester(std::string settings_string)
  { std::cout << "processing settings: " << settings_string << std::endl; }

public:
  std::vector <std::string> settings;
};

int main()
{
  Settings_vector settings_vector;

  using namespace std;
  using namespace std::placeholders;  // for _1

  // Possibility Nr. 1: Use a Lambda Function
  for_each( settings_vector.settings.begin(), settings_vector.settings.end()
          , [&settings_vector](auto input){ settings_vector.tester(input); }
          )
  ;

  // Possibility Nr. 2: Partially bind existing arguments and use placeholders for others 
  for_each( settings_vector.settings.begin(), settings_vector.settings.end()
          , std::bind(&Settings_vector::tester, &settings_vector, _1);
          )
  ;

  return 0;
}

<强>说明:

  • 我认为lambda是直截了当的。在方括号中,您声明了什么进入闭包。在这里,我们通过了settings_vector。在&之前加上意味着此实例通过引用传递。在括号中,我们声明函数的参数。我作弊了一点,因为lambda表达式中的auto是在C ++ 14中引入的,但你也可以把它写成类型std::string

  • std::bind()将参数绑定到函数指针并返回可调用对象。如果存在所有参数,则返回的callable没有参数,可以像:callable()一样调用。在这里,我们希望callable接受迭代的结果。因此,我们使用占位符_1,它声明此参数将在调用时更改。现在剩下两件事了:

    • 获取指向成员函数的指针。这是使用&TypeName::MemberName完成的,在本例中为&Settings_vector::tester

    • this指针传递给成员函数调用:&settings_vector。调用成员函数时,必须传递一个对象,该对象必须为其调用此成员函数。因为我们只有一个指向成员函数的指针而没有任何绑定对象,所以这就是为什么第二个参数是&settings_vector

答案 1 :(得分:0)

为了更简洁的语法,使用静态类方法。我对您的代码进行了轻微编辑,以提高您问题上下文中的可读性(也就是消除干扰)。

#include <iostream>
#include <vector>

class Settings {
  
  public:
    std::vector <std::string> settings;
    
    Settings(std::initializer_list<std::string> l)
    : settings(l) {
    }
  
    static void tester(std::string const& str) {
        std::cout << "processing settings: " << str << std::endl;
    }
};

int main() {
    Settings sv {"settings 1", "settings 2", "settings 3", "settings 4"};
    for_each(sv.settings.begin(), sv.settings.end(), Settings::tester);
    return 0;
}