Могу ли я иметь массив лямбда-указателей для хранения функций с различными типами аргументов / возвращаемых значений? - PullRequest
0 голосов
/ 31 октября 2018

Предположим, у меня есть класс с двумя функциями-членами:

#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 только с их индексом в контейнере и выяснять, как использовать предоставленные аргументы, если вообще используются, с помощью поставляемой лямбда-функции. Предполагается, что это позволит включить класс Command Server, где я получу символ в качестве указанного индекса и аргументы, если таковые имеются, в виде строки через UDP.

Однако компилятор не разрешает мне передавать ссылку на лямбду.

Создание оператора switch-case в MyServerClass, где я вручную ввожу код, который я вставил в лямбда-выражения в примере, неосуществимо, поскольку класс Server не знает о своих родительских методах.

Возможно ли что-то похожее на приведенный пример?

Извините, если пост не соответствует стандартам, мой первый здесь.

Спасибо за вашу помощь!

1 Ответ

0 голосов
/ 31 октября 2018

Причина, по которой ваш лямбда-подход не работает, состоит в том, что вы можете превратить лямбду в указатель на функцию, только если лямбда не имеет перехватов. Однако чтобы использовать / обернуть (нестатическую) функцию-член в лямбде, лямбда-код должен захватывать (хранить) конкретный экземпляр объекта для вызова этой функции-члена в (this), а указатели на функции не могут иметь (неглобальный) ) хранится в таком состоянии. Если вы добавите this в список перехвата, то сами лямбды действительны, но больше не могут распадаться на указатель функции.

std::function позволяет хранить произвольно вызываемые объекты - даже те, у которых есть снимки. Они также, как правило, более читабельны (и имеют более высокий уровень), чем указатели функций.

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

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

  // ...

  vector<MyFunctionType> functionCollection;
}

Теперь MyCommandServer может принимать и хранить ваши лямбды (если вы передаете их по значению), поскольку они могут вызываться со строковым аргументом и возвращать строку.

...