C ++括号初始化列表作为lambda参数

时间:2018-07-25 11:55:23

标签: visual-c++ c++17

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和这小小的情况导致的“可能被删除”还是“将被删除”?

这会消失吗?还是会持续下去...?

1 个答案:

答案 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*是非推论上下文。