为什么我们不能用 auto 声明 std::function

ATK*_*ATK 1 c++ lambda c++20

我得到以下代码:

 template<typename T>
concept con1 = requires(T t, std::string s){
    { t[s] } -> std::same_as<std::string>;
};

using function_signature = std::function<void ( con1 auto  functor)>; // ERROR!
Run Code Online (Sandbox Code Playgroud)

虽然编译器对我直接定义 lambda 没有问题:

auto lambda_1 = [](con1 auto functor){....} 
Run Code Online (Sandbox Code Playgroud)

我希望前者起作用的原因如下:

 template<std::semiregular T>
 class R{

     T functor;
     R() = default;
     register_functor(T functor_) { functor = std::move(functor_);}
  }
Run Code Online (Sandbox Code Playgroud)

如果我使用如下签名实例化我的类:

  auto rr = R<function_signature>(); 
Run Code Online (Sandbox Code Playgroud)

我可以在稍后阶段注册我的函子,甚至可以在运行时更改函数,只要我保持签名相同即可。直接使用 lambda 意味着我在实例化 lambda 时会陷入困境class R

Ben*_*igt 7

auto在 lambda 参数列表中,并不像在变量初始化中那样表示单个自动推断的类型,它表示 lambda 具有一个模板,该模板operator()具有一整套参数化函数签名系列。

您无法实例化需要(并且std::function确实)具有参数化类型系列的具体类型的模板。您可以创建一个参数化的 typedef 系列,每个 typedef 通过实例化形成std::function

template<con1 T> using function_signature = std::function<void (T)>;
Run Code Online (Sandbox Code Playgroud)

但这并不能让您更接近能够编写R<function_signature>. 为此,您需要template<template class T<U>> class R;然后需要以某种方式在 中R提供类型参数。T2T<T2> functor

最后,它归结为std::function指向成员函数的指针(以及其他风格)的包装器,并且指向成员函数的指针不能指向成员函数的整个模板系列。

这也失败了:

auto lambda_1 = [](con1 auto functor){....};
auto pmf = &lambda_1::operator(); // cannot take address of template member function
Run Code Online (Sandbox Code Playgroud)

换句话说,类型擦除不适用于模板。实例化模板需要其类型。