是否可以计算出 lambda 的参数类型和返回类型?
给定一个 lambda,是否可以找出它的参数类型和返回类型?如果是,怎么办?
基本上,我想要 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 作为参数的函数模板中使用 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!
//...
}
目前,我们可以假设 lambda 只接受一个参数。
最初,我尝试使用 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 对象(如上所示)。
Given a lambda, is it possible to figure out it's parameter type and return type? If yes, how?
Basically, I want lambda_traits
which can be used in following ways:
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
The motivation behind is that I want to use lambda_traits
in a function template which accepts a lambda as argument, and I need to know it's parameter type and return type inside the function:
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!
//...
}
For the time being, we can assume that the lambda takes exactly one argument.
Initially, I tried to work with std::function
as:
template<typename T>
A<T> f(std::function<bool(T)> fun)
{
return A<T>(fun);
}
f([](int){return true;}); //error
But it obviously would give error. So I changed it to TLambda
version of the function template and want to construct the std::function
object inside the function (as shown above).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
有趣的是,我刚刚编写了一个
function_traits
实现 基于 在 lambda 上专门化模板C++0x 可以给出参数类型。正如该问题的答案中所述,技巧是使用 lambda 的operator()
的decltype
。请注意,此解决方案不适用于像
[](auto x) {}
这样的通用 lambda。Funny, I've just written a
function_traits
implementation based on Specializing a template on a lambda in C++0x which can give the parameter types. The trick, as described in the answer in that question, is to use thedecltype
of the lambda'soperator()
.Note that this solution does not work for generic lambda like
[](auto x) {}
.虽然我不确定这是否严格符合标准,
ideone 编译了以下代码:
但是,这仅提供了函数类型,因此结果和参数
必须从中提取类型。
如果您可以使用
boost::function_traits
、result_type
和arg1_type
就会达到目的。
由于 ideone 似乎不提供 C++11 模式下的提升,我无法发布
实际的代码,抱歉。
Though I'm not sure this is strictly standard conforming,
ideone compiled the following code:
However, this provides only the function type, so the result and parameter
types have to be extracted from it.
If you can use
boost::function_traits
,result_type
andarg1_type
will meet the purpose.
Since ideone seems not to provide boost in C++11 mode, I couldn't post
the actual code, sorry.
@KennyTMs 答案中显示的专业化方法可以扩展到涵盖所有情况,包括可变参数和可变 lambda:
<强>演示。
请注意,可变参数
operator()
的数量不会调整。相反,我们也可以考虑is_variadic
。The specialization method shown in @KennyTMs answer can be extended to cover all cases, including variadic and mutable lambdas:
Demo.
Note that the arity is not adjusted for variadic
operator()
s. Instead one can also consideris_variadic
.@KennyTMs 提供的答案效果很好,但是如果 lambda 没有参数,则使用索引 arg<0>不编译。如果其他人遇到这个问题,我有一个简单的解决方案(比使用 SFINAE 相关解决方案更简单)。
只需将 void 添加到 arg 结构中元组的末尾,位于可变参数类型之后。即,
由于数量不依赖于模板参数的实际数量,因此实际数量不会不正确,如果它是 0,则至少 arg<0>仍然会存在,你可以用它做你想做的事。如果您已经计划不超过索引
arg
那么它不应该干扰您当前的实现。The answer provided by @KennyTMs works great, however if a lambda has no parameters, using the index arg<0> does not compile. If anyone else was having this problem, I have a simple solution (simpler than using SFINAE related solutions, that is).
Just add void to the end of the tuple in the arg struct after the variadic argument types. i.e.
since the arity isn't dependent on the actual number of template parameters, the actual won't be incorrect, and if it's 0 then at least arg<0> will still exist and you can do with it what you will. If you already plan to not exceed the index
arg<arity-1>
then it shouldn't interfere with your current implementation.这是我的函数特征的玩具版本。我利用了 std::function 的类型推断,而没有实际构建任何 std::function 对象。
这允许使用常规函数,而不仅仅是函子。
感谢 Cœur 的灵感。
Here is my toy version of function traits. I took advantage of
std::function
's type inference without actually building anystd::function
object.This allows working with regular functions, not just functors.
Thanks, Cœur, for the inspiration.
如果您正在为 C++ 中可调用的所有类型寻找完整的解决方案,那么很多答案都有效,但错过了一些极端情况,例如
这是据我所知的完整解决方案(通用 lambda 除外) - 如果缺少任何内容,请在评论中告诉我:
免责声明:
std::remove_reference
的灵感来自 此代码。If you're looking for a complete solution for all types in C++ that can be invoked, a lot of these answers work but miss some of the corner cases, like
Here's a complete solution to my knowledge (except for generic lambdas) - let me know in the comments if anything is missing:
Disclaimer: the
std::remove_reference
was inspired by this code.