是否可以计算出lambda的参数类型和返回类型?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (22)

给定一个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_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!
   //...
}

目前,我们可以假设lambda只需要一个参数。

最初,我试图与std::function

template<typename T>
A<T> f(std::function<bool(T)> fun)
{
   return A<T>(fun);
}

f([](int){return true;}); //error

但它显然会给出错误(ideone)。所以我将它更改TLambda为函数模板的版本,并且想要在函数std::function内部构造对象(如上所示)。

提问于
用户回答回答于

有趣的是,我刚刚写了一个function_traits实现,它基于专门研究C ++ 0x中的lambda模板,可以给出参数类型。这个问题的答案中所描述的技巧是使用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;
}
用户回答回答于

虽然我不确定这是否严格符合标准,但 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, "" );
}

但是,这只提供了函数类型,所以必须从中提取结果和参数类型。如果你能使用boost::function_traitsresult_type并且arg1_type 会达到目的。由于ideone似乎不提供C ++ 11模式的提升,所以我无法发布实际的代码,对不起。

扫码关注云+社区