сопоставить указатель на функцию с разным количеством аргументов и разными типами данных - PullRequest
0 голосов
/ 06 августа 2020

В моем коде у меня есть несколько классов, каждый с разными методами. Например:

class A {
public:
    int sum(int a, int b);
    bool isScalable(double d);
}

class B {
public:
    std:string ownerName();
}

Моя цель - создать карту всех имен функций, как показано ниже

std::map<std::string, FnPtr> myMap;

// Add the newly implemented function to this map
myMap["sum"] = &A::sum;
myMap["isScalable"] = &A::isScalable;
myMap["myMap"] = &B::myMap;

Проблема в том, что я не знаю, как я могу определить FnPtr. Не могли бы вы мне помочь.

1 Ответ

0 голосов
/ 07 августа 2020

Как следует из комментариев, маловероятно, что вы действительно захотите это сделать.

Предполагая, что вы это делаете, однако - возможно, вам следует пересмотреть, является ли C ++ правильным языком для задачи. Другой язык, который имеет лучшие средства отражения во время выполнения, может быть более подходящим; возможно, интерпретируемый язык, например Python или Perl. Обычно это намного удобнее, когда вам нужно искать методы класса по имени во время выполнения.

Если это должен быть C ++, то, возможно, вам следует немного ослабить структуру класса. Используйте один класс как для A, так и для B (назовем его MyCommonObj); и пусть класс хранит карту строк для указателей функций. Что касается сигнатур этих функций - вероятно, неплохо было бы делать не функции-члены, а автономные. В этом случае, возможно, ваш тип указателя функции будет:

using generic_function = std::any (*)(std::vector<std::any>);

Это довольно общий c - для хранения и для вызова. Если у вас есть эта карта, вы можете легко найти имя своей функции и передать аргументы. Однако вам может потребоваться также сохранить дополнительную информацию о том, какого типа должны быть ваши аргументы, иначе вы всегда будете передавать строки. ... что также является вариантом, я полагаю:

using generic_function = std::any (*)(std::vector<std::string>);

Теперь, если члены A и B в вашем примере действительно нестатичны c, как вы их перечислили, т.е. они используют поля экземпляра, тогда эти общие c функции также должны всегда принимать ссылку или указатель на экземпляр MyCommonObj:

using generic_function = std::any (*)(MyCommonObj&, std::vector<std::string>);

Наконец, обратите внимание, что код, использующий этот тип, и поиск во время выполнения имен функций и т.д. c - будет не очень производительно.

Если вы не используете C ++ 17 и у вас нет доступа к std::any, вы можете:

  • Используйте boost::any из библиотек Boost.
  • Используйте любую библиотеку эмулятора (которая существует на GitHub)
  • Используйте объединение всех типов, которые вы действительно используете, например union {int i; double d;} - но тогда вам нужно будет защитить себя от передачи значений неправильный тип.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...