std :: initializer_list的类型推断

use*_*710 0 c++ templates type-inference initializer-list c++11

如果我写这个

std::vector<std::string> v{"one","two","three"};
Run Code Online (Sandbox Code Playgroud)

推断到关联std::initializer_list模板的类型是什么?换句话说,当char *字符串文字转换为std::string

声明它是一个更好的主意

std::vector<std::string> v{std::string("one"),
                           std::string("two"),
                           std::string("three")};
Run Code Online (Sandbox Code Playgroud)

避免与涉及的模板的类型推导机制相关的问题?我会对此保持相同的优化吗?

Arn*_*rtz 7

更新:回答有关类型推断的问题:初始化列表构造函数vector<string>采用initializer_list<string>.它没有模板化,所以在类型推断方面没有任何反应.

尽管如此,这里应用的类型转换和重载解析规则仍有一些兴趣,所以我会让我的初步答案成立,因为你已经接受了它:

原始答案:

首先,编译器只能看到初始化列表 {"one","two","three"},它只是一个初始化列表,而不是该类型的对象std::initializer_list.

然后它尝试找到vector<string>匹配该列表的适当构造函数.如果您对确切的过程感兴趣,那么如何做到这是一个有点复杂的过程,您最好在标准中查找.

因此,编译器决定std::initializer_list<string>初始化列表创建一个实际对象,因为从char*s到std::strings 的隐式转换使得这成为可能.

另一个,也许更有趣的例子:

std::vector<long>   vl1{3};
std::vector<string> vs1{3};
std::vector<string> vs2{0};
Run Code Online (Sandbox Code Playgroud)

这些怎么办?

  1. 第一行相对容易.所述初始化列表 {3}可以被转换成一个std::initializer_list<long>类似于{"onm", "two", "three"}上面的例子中,这样就可以获得与单独的元件,其具有值3的矢量.

  2. 第二行是不同的.它构造了一个3个空字符串的向量.为什么?因为初始化列表 {3}不能转换为a std::initializer_list<string>,所以"普通"构造函数会std::vector<T>::vector(size_t, T = T())启动并提供三个默认构造的字符串.

  3. 那么这个应该与第二个大致相同,对吗?它应该给出一个空向量,换句话说,使用零默认构造的字符串.错误!.在0可以被视为一个空指针常数,并验证std::initializer_list<string>.只有这次该列表中的单个字符串由nullpointer构造,这是不允许的,因此您将获得异常.