我可以使用lambda指针数组来保存具有不同类型的参数/返回值的函数吗?

时间:2018-10-31 16:30:19

标签: c++ function c++11 lambda functor

假设我有一个带有两个成员函数的类:

#include <string>
#include <vector>

using namespace std;

class MyClass{
  MyClass(){
    MyCommandServer server;
    server.addToCollection(&[](string a)->string{return helloWorld();});
    server.addToCollection(&[](string a)->string{return to_string(add(stoi(a[0]),stoi(a[1])));});

    while(true){
      server.pollForCommand();
      doSomethingElse();
    }
  }

  string helloWorld(){
    return "Hello World!";
  }

  int add(int a, int b){
    return a+b;
  }
};

第一个实例化的另一个类:

typedef string (*MyFunctionPointer)(string);

class MyCommandServer{
  MyCommandServer(){}

  void addToCollection(MyFunctionPointer ptr){
    functionCollection.push_back(ptr);
  }

  void pollForCommand(){
    string newCommand = checkForCommand(&args);
    if(newCommand.size()&&isValidCommand(newCommand[0])){
      sendResponseToClient(functionCollection[newCommand[0]](newCommand.substr(1)));
    }
  }

  string checkForCommand();
  bool isValidCommand(char);
  void sendResponseToClient(string);
  vector<MyFunctionPointer> functionCollection;
};

如何将前两个方法传递给addToCollection(MyFunctionPointer)?我想知道是否可以按照示例进行操作。我的目标是要有一种仅在容器中使用索引调用MyClass函数的方法,并通过提供的lambda函数弄清楚如何使用提供的参数(如果有的话)。这应该启用Command Server类,在该类中,我通过UDP获得一个char作为上述索引,并获得一个参数(如果有)作为字符串。

但是,编译器不允许我传递对lambda的引用。

在MyServerClass中进行switch-case语句是不可行的,因为Server类不知道其父方法,因此我在该示例中手动输入了在示例中放入lambda的代码。

是否可以提供与示例类似的内容?

很抱歉,如果该帖子没有达到标准,这是我的第一个帖子。

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

lambda方法不起作用的原因是,如果lambda没有捕获,则只能将lambda转换为函数指针。但是,要在lambda中使用/包装(非静态)成员函数,lambda必须捕获(存储)特定对象实例以在(this上调用该成员函数,并且函数指针不能具有(非-global)这样的存储状态。如果将this添加到捕获列表,则lambda本身是有效的,但不能再衰减到函数指针。

std::function允许您存储任意可调用对象-即使是带有捕获的对象。它们也往往比函数指针更具可读性(和更高层次)。

using MyFunctionType = std::function<std::string(std::string)>;

class MyCommandServer
{
  void addToCollection(MyFunctionType fnc){
    functionCollection.push_back(fnc);
  }

  // ...

  vector<MyFunctionType> functionCollection;
}

现在MyCommandServer可以接受并存储您的lambda(如果您按值传递它们),因为可以使用字符串参数调用它们并返回一个字符串。