为什么我们不能用auto声明std::函数呢



我得到了以下代码:

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!

而编译器可以直接定义lambda:

auto lambda_1 = [](con1 auto functor){....} 

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

template<std::semiregular T>
class R{
T functor;
R() = default;
register_functor(T functor_) { functor = std::move(functor_);}
}

如果我使用签名来实例化我的类,比如:

auto rr = R<function_signature>(); 

我可以在稍后阶段注册我的函子,甚至在运行时更改函数,只要我保持签名不变。直接使用lambda意味着在实例化class R时,无论lambda是什么,我都会被卡住

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

不能使用参数化的类型族实例化需要具体类型的模板(std::function需要)。您可以创建一个参数化的typedef家族,每个typedef都是通过实例化std::function:形成的

template<con1 T> using function_signature = std::function<void (T)>;

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

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

这也会失败:

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

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

最新更新