【问题标题】:Passing a class member function to for_each将类成员函数传递给 for_each
【发布时间】:2017-05-09 21:09:49
【问题描述】:

我的问题是:如何将类成员函数传递给 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;
}

【问题讨论】:

  • 我在示例中添加了更多解释。如果帖子回答了您的问题,如果您能接受,那就太好了。

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


【解决方案1】:

最简单的方法是使用 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。在它前面加上&amp; 意味着这个实例是通过引用传递的。在括号中,我们声明了函数的参数。我作弊了一点,因为 lambda 表达式中的 auto 是在 C++14 中引入的,但您也可以将其写为 std::string 类型。

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

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

    • this 指针传递给成员函数调用:&amp;settings_vector。调用成员函数时,必须传递调用该​​成员函数的对象。因为我们只是得到了一个指向没有任何绑定对象的成员函数的指针,所以第二个参数是&amp;settings_vector

【讨论】:

    【解决方案2】:

    要获得更简洁的 sintax,请使用静态类方法。我稍微编辑了您的代码,以提高您问题上下文中的可读性(也就是消除干扰)。

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

    【讨论】:

    • 这是对问题的回答:GCC 编译器通过使用静态类方法提出了一种更简洁的 sintax。作为实现示例提供的代码。
    猜你喜欢
    • 2017-06-25
    • 2020-09-06
    • 1970-01-01
    • 2019-09-27
    • 1970-01-01
    • 2021-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多