Учитывая лямбду, возможно ли выяснить ее тип параметра и тип возвращаемого значения? Если да, то как?
В принципе, я хочу, lambda_traits
который может быть использован следующими способами:
auto lambda = [](int i) { return long(i*10); };
lambda_traits<decltype(lambda)>::param_type i; //i should be int
lambda_traits<decltype(lambda)>::return_type l; //l should be long
Мотивация заключается в том, что я хочу использовать lambda_traits
в шаблоне функции, который принимает лямбду в качестве аргумента, и мне нужно знать его тип параметра и тип возвращаемого значения внутри функции:
template<typename TLambda>
void f(TLambda lambda)
{
typedef typename lambda_traits<TLambda>::param_type P;
typedef typename lambda_traits<TLambda>::return_type R;
std::function<R(P)> fun = lambda; //I want to do this!
//...
}
Пока можно предположить, что лямбда принимает ровно один аргумент.
Изначально я пытался работать с std::function
:
template<typename T>
A<T> f(std::function<bool(T)> fun)
{
return A<T>(fun);
}
f([](int){return true;}); //error
Но это, очевидно, даст ошибку. Поэтому я изменил его на TLambda
версию шаблона функции и хочу создать std::function
объект внутри функции (как показано выше).
Ответы:
Забавно, я только что написал
function_traits
реализацию, основанную на Специализации шаблона для лямбды в C ++ 0x, которая может давать типы параметров. Хитрость, как описано в ответе на этот вопрос, заключается в использовании лямбды .decltype
operator()
Обратите внимание, что это решение не работает для общего лямбда, как
[](auto x) {}
.источник
tuple_element
Хотя не думал , спасибо.const
, для тех лямбда объявляетсяmutable
([]() mutable -> T { ... }
).operator()
не с этой реализацией.auto
это не тип, поэтому он никогда не может быть ответомtraits::template arg<0>::type
Хотя я не уверен, что это строго соответствует стандартам, ideone скомпилировал следующий код:
Однако это обеспечивает только тип функции, поэтому из него должны быть извлечены типы результатов и параметров. Если вы можете использовать
boost::function_traits
,result_type
иarg1_type
будет соответствовать цели. Так как ideone, похоже, не обеспечивает повышение в режиме C ++ 11, я не смог опубликовать реальный код, извините.источник
Метод специализации, показанный в ответе @KennyTMs, может быть расширен, чтобы охватить все случаи, включая вариабельные и изменяемые лямбды:
Demo .
Обратите внимание, что арность не корректируется для вариационных
operator()
s. Вместо этого можно также рассмотретьis_variadic
.источник
Ответ, предоставленный @KennyTMs, прекрасно работает, однако, если лямбда не имеет параметров, использование индекса arg <0> не компилируется. Если у кого-то еще была эта проблема, у меня есть простое решение (проще, чем использование решений, связанных с SFINAE).
Просто добавьте void в конец кортежа в структуре arg после типов аргументов variadic. т.е.
поскольку арность не зависит от фактического количества параметров шаблона, фактические значения не будут неправильными, и если оно равно 0, то по крайней мере аргумент <0> все еще будет существовать, и вы можете делать с ним все, что захотите. Если вы уже планируете не превышать индекс,
arg<arity-1>
он не должен мешать вашей текущей реализации.источник