是否可以确定 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 对象(如上图)。

原文由 Nawaz 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 811
2 个回答

有趣的是,我刚刚写了一个 function_traits 实现,它基于 Specializing a template on a lambda in C++0x 可以提供参数类型。如该问题的答案所述,诀窍是使用 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;
}

请注意,此解决方案 不适 用于像 [](auto x) {} 这样的通用 lambda。

原文由 kennytm 发布,翻译遵循 CC BY-SA 3.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_typearg1_type 将达到目的。由于 ideone 似乎没有在 C++11 模式下提供增强功能,因此我无法发布实际代码,抱歉。

原文由 Ise Wisteria 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题