Я хотел бы иметь одну карту, которая отображает строковые ключи либо std::function<T()>
или же std::function<T(int)>
(но не оба для данного ключа). Я получаю сообщение об ошибке компиляции, для которого нет шаблона std::function<T(...)>
, Я хотел бы иметь возможность использовать лямбда-выражения в качестве значений.
Во-первых, это безопасный хранить функции таким образом? Во-вторых, если так, какой будет синтаксис? (Была ли функция унарной или нулевой, будет известно, когда она будет извлечена из карты.) И если бы ничего из вышеперечисленного не было, какой была бы разумная альтернатива? Указатели убивают лямбда-идею, верно …
С ++ 11 в порядке.
Одна альтернатива заключается в том, чтобы обернуть нулевые функции в лямбду-обертку, которая принимает один аргумент, ничего не делает с ним и просто вызывает обернутую функцию. Тогда все на вашей карте является унарной функцией.
Конечно, если вы знаете во время поиска, какой тип функции (что, я думаю, вам нужно, иначе она бесполезна!), То почему бы просто не использовать две карты?
Может быть попробовать boost::variant
?
std::map<std::string, boost::variant<std::function<T()>, std::function<T(int)> > >
Во всяком случае, это похоже на XY вопрос. Какие именно так ты пытаешься сделать?
пустой std::function
не такие тяжелые. Вы можете просто сопоставить со структурой, содержащей один из каждого. Вы знаете, что является действительным, так что только доступ к нему.
Если у вас есть шаблон кода, который должен работать с обоими одинаково без передачи в качестве аргумента:
#include <string>
#include <functional>
#include <map>
#include <tuple>
#include <iostream>
#include <math.h>
template<typename T>
using my_maps = std::tuple< std::map<std::string, std::function<T()>>, std::map<std::string, std::function<T(int)>>>;int main() {
my_maps<double> maps;
std::get<0>(maps)["pi"] = [](){ return 3.14; };
std::get<1>(maps)["e^"] = [](int x){ return pow( 2.7, x ); };
std::cout << std::get<1>(maps)["e^"](2) << "\n";
std::cout << std::get<0>(maps)["pi"]() << "\n";
}
Это имеет две карты, с разницей в доступе get<0>
или get<1>
, Это имеет то преимущество, что если вы выбираете, к какому из двух элементов получить доступ в шаблоне, он может выбрать 0 или 1 статически и использовать общий код. Если вам это не нужно, просто два std::map
s.
boost::variant
также работает (карта на variant
или 0ary или 1ary функции). Вы также можете использовать C ++ 11 union
(с примечанием, что у него не будет конструктора по умолчанию или конструктора копирования, если вы его не предоставите) в struct
с перечислением (которое делает копию union
) — в основном гетто boost::variant
,