C ++: Синтаксис для карты, где тип данных является функцией? - PullRequest
1 голос
/ 26 мая 2010

В C # то, что я хочу, выглядело бы примерно так:

IDictionary<string, action()> dict = new Dictionary<string, action()>();

Как мне это сделать в C ++? Это дает ошибки компилятора:

map<string, void()> exercises;

Ответы [ 3 ]

6 голосов
/ 26 мая 2010

Используйте boost :: function , полиморфную оболочку для любого объекта, который может быть вызван с вашей подписью (включая функции, объекты функций и т. Д.).

map<string, function<void()>> ...;

Обратите внимание, что новый стандарт C ++ уже включает function в <functional>.


Для объяснения фона: Единственный встроенный механизм такого рода в C ++ - это старые указатели функций в стиле C (void (*)()). Это чрезвычайно низкоуровневые, в основном просто хранящие адрес памяти функции, и поэтому далекие от того, чтобы даже приблизиться к мощности делегатов C #.

Вы не можете создавать анонимные функции, а также не можете ссылаться на функции-члены конкретного объекта или любые переменные или данные (замыкания).

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

Проблема в том, что эти функторы часто состоят из своеобразных или анонимных типов, на которые нельзя ссылаться удобно.

function - самый крутой способ решить их все - все, что ведет себя как функция, включая новые классные выражения в лямбда-стиле.

function<void()> f = []() { cout << "Hello, World"> };
f();
3 голосов
/ 26 мая 2010

В C ++ необходимо использовать указатели на функции. Используя ваш пример C ++, вы можете вставить его как:

map<string, void(*)()> exercises;

Но случайному наблюдателю может быть полезнее сделать это в две строки:

typedef void (*pointer_to_void_function)();
map<string, pointer_to_void_function> exercises;

(Выберите подходящие имена).

Обратите внимание, что случайным наблюдателям, вероятно, еще проще добавить еще один typedef ...

typedef void (*pointer_to_void_function)();
typedef map<string, pointer_to_void_function> ExerciseMapping;
ExerciseMapping exercises;

Затем, когда вы хотите использовать итераторы или что-то еще, вы просто набираете ExerciseMapping::iterator вместо необходимости набирать карту ... вещи. (Это также облегчает изменение вашей реализации позже.)

0 голосов
/ 26 мая 2010

Попробуйте использовать функциональный объект. Например, вы можете использовать boost :: function .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...