模板的协方差规则
rules on convariance for templates
为什么 initializer_list<string> ls = {"A", "B", "C"};
有效?
rhs是intializer_list<const char*>
的,不知道怎么转成lhs的
同样,vector<string> vs = {"A", "B", "C"}
是如何工作的?
右边是intializer_list<const char*>
这是错误的。右侧没有类型。它不是 initializer_list
类型的对象。它是 braced-init-list,一种特殊的语言结构,用于多种上下文。
[dcl.init.list]/3 关于你的第一个问题是这样说的:
List-initialization of an object or reference of type T is defined as follows:
[...]
— Otherwise, if T
is a specialization of std::initializer_list<E>
, a prvalue initializer_list
object is constructed as described below and used to initialize the object according to the rules for initialization of an object from a class of the same type (8.5).
[dcl.init.list]/5:
An object of type std::initializer_list<E>
is constructed from an initializer list as if the implementation allocated a temporary array of N elements of type const E, where N is the number of elements in the initializer list
. Each element of that array is copy-initialized with the corresponding element of the initializer list, and the std::initializer_list<E>
object is constructed to refer to that array. [ Note: A constructor or conversion function selected for the copy shall be accessible (Clause 11) in the context of the initializer list. —end note ] If a narrowing conversion is required to initialize any of the elements, the program is ill-formed.
简而言之:
首先它为 3 个字符串的数组分配内存
然后它尝试用 init-list 中的相应元素初始化每个字符串。列表的所有元素都可以转换为 const char*
并且 std::string
具有接受 const char*
的构造函数,因此它用于构造这些字符串。
在你的第二个问题中,使用了 [dcl.init.list]/3 中的另一个子句:
List-initialization of an object or reference of type T is defined as follows:
[...]
— Otherwise, if T
is a class type, constructors are considered. The applicable constructors are enumerated and the best one is chosen through overload resolution (13.3, 13.3.1.7). If a narrowing conversion (see below) is required to convert any of the arguments, the program is ill-formed.
vector<string>
有一个采用 initializer_list<string>
的构造函数。在这种情况下这是最佳匹配,我们回到阶段 1:我们需要从 braced-init-list 构造 initializer_list<string>
,我们已经知道该怎么做。
为什么 initializer_list<string> ls = {"A", "B", "C"};
有效?
rhs是intializer_list<const char*>
的,不知道怎么转成lhs的
同样,vector<string> vs = {"A", "B", "C"}
是如何工作的?
右边是intializer_list<const char*>
这是错误的。右侧没有类型。它不是 initializer_list
类型的对象。它是 braced-init-list,一种特殊的语言结构,用于多种上下文。
[dcl.init.list]/3 关于你的第一个问题是这样说的:
List-initialization of an object or reference of type T is defined as follows:
[...]
— Otherwise, ifT
is a specialization ofstd::initializer_list<E>
, a prvalueinitializer_list
object is constructed as described below and used to initialize the object according to the rules for initialization of an object from a class of the same type (8.5).
[dcl.init.list]/5:
An object of type
std::initializer_list<E>
is constructed from an initializer list as if the implementation allocated a temporary array of N elements of type const E, where N is the number of elements in theinitializer list
. Each element of that array is copy-initialized with the corresponding element of the initializer list, and thestd::initializer_list<E>
object is constructed to refer to that array. [ Note: A constructor or conversion function selected for the copy shall be accessible (Clause 11) in the context of the initializer list. —end note ] If a narrowing conversion is required to initialize any of the elements, the program is ill-formed.
简而言之:
首先它为 3 个字符串的数组分配内存
然后它尝试用 init-list 中的相应元素初始化每个字符串。列表的所有元素都可以转换为
const char*
并且std::string
具有接受const char*
的构造函数,因此它用于构造这些字符串。
在你的第二个问题中,使用了 [dcl.init.list]/3 中的另一个子句:
List-initialization of an object or reference of type T is defined as follows:
[...]
— Otherwise, ifT
is a class type, constructors are considered. The applicable constructors are enumerated and the best one is chosen through overload resolution (13.3, 13.3.1.7). If a narrowing conversion (see below) is required to convert any of the arguments, the program is ill-formed.
vector<string>
有一个采用 initializer_list<string>
的构造函数。在这种情况下这是最佳匹配,我们回到阶段 1:我们需要从 braced-init-list 构造 initializer_list<string>
,我们已经知道该怎么做。