MSVC CL版本19.14.26433.0
情况是这样的:
auto string_tester = []( auto std_string ) { };
// creates proper std::initializer_list instance
auto init_list = { "narrow string" };
// compiles and works
string_tester(init_list);
但是。该不该编译吗?
// does not compile
string_tester({ "narrow string" } ) ;
请讨论。
[更新]
全部感谢您的回答。显然,发送初始化列表时无法推断出lambda候选模板参数。
我很好奇。是C ++ 20通用lambda和这小小的情况导致的“可能被删除”还是“将被删除”?
这会消失吗?还是会持续下去...?
答案 0 :(得分:1)
[dcl.type.auto.deduct] / 4 如果占位符是
auto
type-specifier ,则推导类型T1
替换T
是使用模板自变量推导规则确定的。通过用新的发明类型模板参数P
替换T
的出现auto
来获取U
,或者如果初始化是复制列表初始化,则用{{ 1}}。使用来自函数调用( [temp.deduct.call] )的模板参数推导规则推导std::initializer_list<U>
的值,其中U
是函数模板参数类型,相应的参数为P
。[temp.deduct.call] / 1 通过比较包含 template-parameters 的每个函数模板参数类型(称为
e
)来完成模板参数推导。 em>参与模板自变量推导,其调用类型为相应的自变量(称为P
),如下所述。如果从A
中删除引用和cv限定词,则会给P
...带来std::initializer_list<P1>
...,并且该参数是非空的初始化列表(11.6.4),则可以推导而是对初始化器列表的每个元素执行,以P1
作为函数模板参数类型,并将初始化器元素作为其参数...否则,初始化器列表参数导致该参数被视为非推论上下文
这就是P1
无法编译的原因:lambda具有string_tester({ "narrow string" } ) ;
作为函数模板,并且其模板参数无法从初始值设定项列表参数推导出。
由于 [dcl.type.auto.deduct] / 4 中的特殊规定,对于operator()
进行的扣除就好像您已经
auto init_list = { "narrow string" };
然后在{strong> [temp.deduct.call] / 1 的前半部分和template <typename U> void f(std::initializer_list<U>);
f({ "narrow string" });
分别为{{1 }}。
另一方面,具有通用lambda调用的情况等同于
U
这遵循 [temp.deduct.call] / 1 的“其他”部分,其中const char*
是非推论上下文。