Naw*_*waz 133 c++ lambda metaprogramming traits c++11
给定一个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
Run Code Online (Sandbox Code Playgroud)
背后的动机是我想lambda_traits在一个接受lambda作为参数的函数模板中使用,我需要知道它的参数类型和函数内部的返回类型:
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!
//...
}
Run Code Online (Sandbox Code Playgroud)
目前,我们可以假设lambda只接受一个参数.
最初,我尝试使用std::function:
template<typename T>
A<T> f(std::function<bool(T)> fun)
{
return A<T>(fun);
}
f([](int){return true;}); //error
Run Code Online (Sandbox Code Playgroud)
但它显然会给出错误.所以我将其更改TLambda为函数模板的版本,并希望在函数std::function内部构造对象(如上所示).
ken*_*ytm 157
有趣的是,我刚刚编写了一个基于在C++ 0x中的lambda上专门化模板的function_traits实现,它可以给出参数类型.如该问题的答案所述,诀窍是使用lambda的. decltypeoperator()
template <typename T>
struct function_traits
: public function_traits<decltype(&T::operator())>
{};
// For generic types, directly use the result of the signature of its 'operator()'
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
// we specialize for pointers to member function
{
enum { arity = sizeof...(Args) };
// arity is the number of arguments.
typedef ReturnType result_type;
template <size_t i>
struct arg
{
typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
// the i-th argument is equivalent to the i-th tuple element of a tuple
// composed of those arguments.
};
};
// test code below:
int main()
{
auto lambda = [](int i) { return long(i*10); };
typedef function_traits<decltype(lambda)> traits;
static_assert(std::is_same<long, traits::result_type>::value, "err");
static_assert(std::is_same<int, traits::arg<0>::type>::value, "err");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
请注意,此解决方案不适用于通用lambda [](auto x) {}.
Ise*_*ria 11
虽然我不确定这是严格的标准符合, 但是ideone编译了以下代码:
template< class > struct mem_type;
template< class C, class T > struct mem_type< T C::* > {
typedef T type;
};
template< class T > struct lambda_func_type {
typedef typename mem_type< decltype( &T::operator() ) >::type type;
};
int main() {
auto l = [](int i) { return long(i); };
typedef lambda_func_type< decltype(l) >::type T;
static_assert( std::is_same< T, long( int )const >::value, "" );
}
Run Code Online (Sandbox Code Playgroud)
但是,这仅提供函数类型,因此必须从中提取结果和参数类型.如果可以使用boost::function_traits,result_type并且arg1_type
将满足目的.由于ideone似乎不提供C++ 11模式的提升,我无法发布实际代码,抱歉.
@KennyTMs答案中显示的专门化方法可以扩展到涵盖所有情况,包括可变参数和可变lambda:
template <typename T>
struct closure_traits : closure_traits<decltype(&T::operator())> {};
#define REM_CTOR(...) __VA_ARGS__
#define SPEC(cv, var, is_var) \
template <typename C, typename R, typename... Args> \
struct closure_traits<R (C::*) (Args... REM_CTOR var) cv> \
{ \
using arity = std::integral_constant<std::size_t, sizeof...(Args) >; \
using is_variadic = std::integral_constant<bool, is_var>; \
using is_const = std::is_const<int cv>; \
\
using result_type = R; \
\
template <std::size_t i> \
using arg = typename std::tuple_element<i, std::tuple<Args...>>::type; \
};
SPEC(const, (,...), 1)
SPEC(const, (), 0)
SPEC(, (,...), 1)
SPEC(, (), 0)
Run Code Online (Sandbox Code Playgroud)
演示.
请注意,未针对可变参数调整arity operator().相反,人们也可以考虑is_variadic.
| 归档时间: |
|
| 查看次数: |
26630 次 |
| 最近记录: |