考虑以下示例:
#include <initializer_list>
#include <vector>
#include <string>
#include <type_traits>
int main() {
std::vector<std::string> svec;
// Non-ambigously deduced to std::initializer_list<char>.
auto a = {'a', 'b'};
static_assert(std::is_same_v<std::initializer_list<char>, decltype(a)>);
// (A)
// error: no match for 'operator=' (... std::vector<std::string> and 'std::initializer_list<char>')
//svec = a;
//svec = std::initializer_list<char>{'a', 'b'};
// error:
// error: unable to deduce 'std::initializer_list<auto>' from '{{'a', 'b'}}'
//auto b = {{'a', 'b'}};
// (B)
// OK.
// After all the following copy assingnments, svec.size() is 1 (a single "ab" element).
svec = {{'a', 'b'}};
svec = std::initializer_list<std::string>{{'a', 'b'}};
svec = std::initializer_list<std::string>{std::initializer_list<char>{'a', 'b'}};
svec = std::initializer_list<std::string>{"ab"};
}
(A) 处的错误消息是不言自明的:不存在用于 std::vector<std::string> 的复制赋值运算符来为其分配 std::initializer_list<char> 参数。 std::vector<T,Allocator>::operator= 唯一可行的重载需要std::initializer_list<T> 类型的参数:
vector& operator=( std::initializer_list<T> ilist );
用初始化列表ilist标识的内容替换内容。
但是在这个例子中T 是std::string,因此这个重载是不可行的。
另一方面,在(B)中,我们使用嵌套的大括号初始化语法{{'a', 'b'}},使得内部大括号初始化列表代表std::initializer_list<char>,可以使用the following std::string constructor:
basic_string( std::initializer_list<CharT> ilist,
const Allocator& alloc = Allocator() );
创建一个 single std::string 临时,它又是外部大括号初始化列表的一部分,利用上面提到的std::vector 复制赋值运算符:
vector& operator=( std::initializer_list<T> ilist )
(B)的不同变化的结果是相同的:复制分配给svec向量一个单个std::string元素的向量。
最后,请注意,如果您要使用" 分隔的字符串 的花括号初始化列表将assign 复制到svec,结果是复制分配两个元素的向量:
svec = {"a", "b"}; // svec.size() is now 2
因为我们没有直接创建 两个元素的std::initializer_list<std::string>,而上面的几个字符的std::initializer_list<char>会导致单个字符串。即,单个std::string 对象也是(零或)多个char 元素的容器。