c++ - c++11/1y lambda 函数的类型签名是什么?

标签 c++ c++11 lambda

我想知道是否有一种标准方法来获取任何给定 lambda 的参数的类型签名(即返回类型和类型)?

我问的原因是我一直想知道 auto 到底是什么类型在声明中,如 auto l =[](int x,int y)->int{return x+y;} .在 auto 的其他用例中,对于较长的类型名称,它是一种方便且较短的替代方法。但是对于 lambdas,是否还有另一种声明 lambda 变量的方法?

我的理解是,一个标准的 lambda 只不过是一个函数对象,它是它自己的类型。因此,即使两个 lambda 具有相同的返回类型和参数类型,它们仍然是两个不同的、不相关的类/仿函数。但这有办法捕捉它们在类型签名方面相同的事实吗?

我认为我正在寻找的类型签名可能类似于 std::function<>正确类型的对象。

一个更有用/涉及的问题是,如果可以提取类型签名,则可以编写一个通用包装函数将任何 lambda 函数转换为 std::function同类型签名的对象。

最佳答案

根据Can the 'type' of a lambda expression be expressed? ,实际上在当前的 c++ 中(不需要 c++1y)有一种简单的方法来计算 lambda 的 return_type 和参数类型。适应这个,不难组装一个std::function为每个 lambda 键入签名类型(以下称为 f_type)。

我。使用这种抽象类型,实际上可以有一个替代方法 auto用于表示 lambda 的类型签名,即 function_traits<..>::f_type以下。注:f_type不是 lambda 的真实类型,而是 lambda 类型签名在函数方面的总结。然而,它可能比 lambda 的真实类型更有用,因为每个 lambda 都是它自己的类型

如下代码所示,就像可以使用 vector<int>::iterator_type i = v.begin() ,也可以做function_traits<lambda>::f_type f = lambda ,它是神秘 auto 的替代品.当然,这种相似性只是形式上的。下面的代码涉及将 lambda 转换为 std::function与构造 std::function 的类型删除成本对象和通过 std::function 进行间接调用的少量成本目的。但是这些使用 std::function 的实现问题除了(我不认为这是基本的并且应该永远存在)之外,毕竟可以显式地表达任何给定 lambda 的(抽象)类型签名。

二。也可以写一个make_function包装器(很像 std::make_pairstd::make_tuple )自动转换 lambda f (和其他可调用对象,如函数指针/仿函数)到 std::function ,具有相同的类型推导功能。

测试代码如下:

#include <cstdlib>
#include <tuple>
#include <functional>
#include <iostream>
using namespace std;

// For generic types that are functors, delegate to its 'operator()'
template <typename T>
struct function_traits
    : public function_traits<decltype(&T::operator())>
{};

// for pointers to member function
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const> {
    //enum { arity = sizeof...(Args) };
    typedef function<ReturnType (Args...)> f_type;
};

// for pointers to member function
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) > {
    typedef function<ReturnType (Args...)> f_type;
};

// for function pointers
template <typename ReturnType, typename... Args>
struct function_traits<ReturnType (*)(Args...)>  {
  typedef function<ReturnType (Args...)> f_type;
};

template <typename L> 
typename function_traits<L>::f_type make_function(L l){
  return (typename function_traits<L>::f_type)(l);
}

long times10(int i) { return long(i*10); }

struct X {
  double operator () (float f, double d) { return d*f; } 
};

// test code
int main()
{
    auto lambda = [](int i) { return long(i*10); };
    typedef function_traits<decltype(lambda)> traits;
    traits::f_type ff = lambda;

    cout << make_function([](int i) { return long(i*10); })(2) << ", " << make_function(times10)(2) << ", " << ff(2) << endl;
    cout << make_function(X{})(2,3.0) << endl;

    return 0;
}

关于c++ - c++11/1y lambda 函数的类型签名是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21657627/

相关文章:

Java 8 如何将非功能性方法作为参数传递

具有参数类型的 C# Func 委托(delegate)

c++ - 在 Windows 下使用共享内存。如何传递不同的数据

c++ - 使用 {a,b,c} 作为参数的构造函数或 {a,b,c} 实际上在做什么?

c++ - 确保模板化泛型参数的返回类型

vector 的 C++ STL vector 和内存管理

c++ - 编译器能否优化对可能产生副作用的函数的调用?

C++ 读/写二进制模式

c++ - icc版本13.0.0标志进行编译

c# - 如何使用 List<String> 变量过滤强类型列表