Универсальный std::function для хранения универсального лямбда-выражения
Когда общая лямбда хранится как std::function
нам нужно предоставить конкретный тип, что-то вроде,
std::function<double(double)>
таким образом, привязка к определенному типу,
Следующая декларация:
std::function<auto(auto)>
выдает ошибку компилятора.
Я понимаю, что, начиная с C++14, auto
может использоваться для хранения возвращаемого значения лямбда-выражения, но есть ли способ добиться этого при хранении лямбда-выражения в std::function
?
2 ответа
Ты не можешь Даже с кастомом не написал std::function
, Это фундаментальный предел стирания типа.
Интуитивно, шаблоны требуют информацию о типе, доступную в точке вызова функции, но стирают тип в std::function
уничтожает эту информацию.
На более детальном уровне стирание типов работает путем сохранения набора операций независимо от типа во время компиляции, либо неявно с помощью виртуальных функций, либо явно с помощью указателей на функции. Шаблоны фактически представляют собой бесконечное семейство операций, поэтому их невозможно сохранить.
Если вы знаете фиксированный набор сигнатур функций, которые вы будете использовать, вы можете написать std::function
,
Ты не можешь
Общий лямбда и std::function
это совершенно разные вещи.
Вы можете грубо увидеть auto(auto)
лямбда как не шаблонный класс с шаблоном operator()
,
Что-то как
struct myUnnamedLambdaStruct
{
// ...
template <typename T>
auto operator() (T t) const
{ /* .... */ };
};
куда std::function()
наоборот: это (специализация) шаблонный класс с не-шаблоном operator()
template <typename>
class function;
template <typename RetType, typename ... ArgTypes>
class function<RetType(ArgTypes...)>
{
// a lot of other members/methods
public:
RetType operator() (ArgTypes ... args) const
{ /* .... */ }
};
Таким образом, общий лямбда-объект не содержит ни одного operator()
но набор operator()
где std::function
объект содержит один operator()
,
Вы можете "сохранить" общую лямбду в std::function
но только исправление, один раз для всех, RetType
и ArgTypes...
, То есть: выбор одного operator()
, в доступном наборе operator()
и забывая обо всех остальных.