#c #templates #lambda
Вопрос:
мы знаем, что decltype()
это может быть использовано для получения типа переменных, как показано ниже:
int a = 0;
using a_t = decltype(a);
a_t b = -1; // it worked, and type of b is int
но это не сработало для этого:
auto f = [](int a) -> int { return a 1;}; // the type of callable should be int(int)?
std::function<decltype(f)> F(f); // error
std::function<int(int)> G(f); // worked
почему? и есть ли какой-либо метод для получения типа функции(в <>
) лямбда-выражения?
Комментарии:
1. отсутствует
;
послеa 1
и, пожалуйста, включите сообщение об ошибке в вопрос2. тип лямбда-выражения не является типом функции , который требуется
std::function
.3. для вывода типа функции лямбда-выражения можно использовать
decltype(lambda::operator())
, за исключением того , что это универсальное лямбда-выражение.4. С c 17 или более поздней версии вы можете это сделать
std::function F(f);
благодаря CTAD .
Ответ №1:
Это просто неправильное использование std::function
оболочки. Этот тип предназначен для того, чтобы скрыть фактическую реализацию, обернув ее в объект, стираемый по типу, с как можно меньшим количеством информации о базовом вызываемом объекте: и это сигнатура функции.
При использовании вы decltype(f)
получаете уникальный , созданный компилятором тип лямбда-выражения. Но это не то , как вы можете создать экземпляр a std::function
, так как базовый, неспециализированный шаблон template<class> std::function
не определен. Определена только специализация template<class R, class ...Args> std::function<R(Args...)>
, и вы не можете создать ее экземпляр с типом лямбда-выражения.
Обратите внимание, что все лямбда-выражения также имеют подпись: они принимают некоторые аргументы (возможно, типы параметров шаблона) и возвращают значение определенного типа. Это информация, которую вам нужно ввести в создание std::function
экземпляра. В вашем случае int(int)
, как вы сами написали.
Ответ №2:
Существует ли какой-либо метод для получения типа функции (в
<>
) лямбда-выражения?
Да, для непатентованных лямбд без захвата существует определенная пользователем функция преобразования для получения эквивалентного типа указателя функции. Вот как вы можете это использовать:
#include <functional>
#include <type_traits>
auto f = [](int a) -> int { return a 1;};
template <class F>
using fn_type_t = std::remove_pointer_t<decltype( std::declval<F>())>;
std::function<fn_type_t<decltype(f)>> F(f);
Унарный
оператор запускает преобразование в int(*)(int)
, а затем std::remove_pointer
получает int(int)
из типа этого выражения.