我得到了以下代码:
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是什么,我都会被卡住
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
换句话说,类型擦除对模板不起作用。实例化模板需要其类型。