在对向量的初始化中
std::vector<std::pair<int, std::string>> foo{{1.0, "one"}, {2.0, "two"}};
我该如何解释 foo
的结构?据我了解,
- 使用大括号初始化语法调用构造函数,因此重载
vector( std::initializer_list<T> init, const Allocator& alloc = Allocator() );
强烈偏好和选择 std::initializer_list<T>
的模板参数推导为std::pair<int, std::string>
foo
的每个元素是std::pair
。然而,std::pair
没有过载接受std::initializer_list
.
我对步骤 3 不太确定。我知道内部大括号不能解释为 std::initializer_list
因为它们是异质的。标准中的什么机制实际上正在构建 foo
的每个元素?我怀疑答案与将内部大括号中的参数转发到重载 template< class U1, class U2 pair( U1&& x, U2&& y );
有关。但我不知道这叫什么。
编辑:
我认为提出同样问题的一种更简单的方法是:当一个人这样做时
std::map<int, std::string> m = { // nested list-initialization
{1, "a"},
{2, {'a', 'b', 'c'} },
{3, s1}
如the cppreference example所示,标准中哪里说 {1, "a"}
, {2, {'a', 'b', 'c'} }
,和{3, s1}
每个都被转发到 std::pair<int, std::string>
的构造函数?
最佳答案
通常,表达式是从内到外分析的:内部表达式具有类型,然后这些类型决定外部运算符的含义以及要调用哪些函数。
但是初始值设定项列表不是表达式,并且没有类型。因此,由内而外是行不通的。需要特殊的重载解析规则来考虑初始化列表。
第一条规则是:如果存在带有单个参数的构造函数,则为 initializer_list<T>
,那么在第一轮重载决策中,仅考虑此类构造函数 ( over.match.list )。
第二条规则是:对于每个 initializer_list<T>
(每个类可能有多个候选者,每个都有不同的 T
),检查每个初始值设定项是否可以转换为 T
,并且只有那些候选者会保留在该结果中 ( over.ics.list )。
第二条规则基本上是采用初始化列表无类型障碍并恢复由内而外的分析。
一旦重载决议决定特定的initializer_list<T>
应该使用构造函数,复制初始化用于初始化 elements of type T
of the initializer列表。
关于c++11 - 嵌套列表初始化如何转发其参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62030516/