карта, содержащая std :: function & lt; T () & gt; и std :: function & lt; T (int) & gt;

Я хотел бы иметь одну карту, которая отображает строковые ключи либо std::function<T()> или же std::function<T(int)> (но не оба для данного ключа). Я получаю сообщение об ошибке компиляции, для которого нет шаблона std::function<T(...)>, Я хотел бы иметь возможность использовать лямбда-выражения в качестве значений.

Во-первых, это безопасный хранить функции таким образом? Во-вторых, если так, какой будет синтаксис? (Была ли функция унарной или нулевой, будет известно, когда она будет извлечена из карты.) И если бы ничего из вышеперечисленного не было, какой была бы разумная альтернатива? Указатели убивают лямбда-идею, верно …

С ++ 11 в порядке.

0

Решение

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

Конечно, если вы знаете во время поиска, какой тип функции (что, я думаю, вам нужно, иначе она бесполезна!), То почему бы просто не использовать две карты?

5

Другие решения

Может быть попробовать boost::variant?

std::map<std::string, boost::variant<std::function<T()>, std::function<T(int)> > >

Во всяком случае, это похоже на XY вопрос. Какие именно так ты пытаешься сделать?

2

пустой 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::maps.

boost::variant также работает (карта на variant или 0ary или 1ary функции). Вы также можете использовать C ++ 11 union (с примечанием, что у него не будет конструктора по умолчанию или конструктора копирования, если вы его не предоставите) в struct с перечислением (которое делает копию union) — в основном гетто boost::variant,

2
По вопросам рекламы [email protected]