简短的回答
For s2, 使用大括号语法,并且{a.begin(), a.end()}被认为是initializer_lists的一个std::array<int>::iterator。因此,s2是一组迭代器。
对于s3,使用括号语法,并选择迭代器构造函数。s3是ints 的集合,并从范围 中初始化[a.begin(), a.end())。
长答案
根据[set.overview],我们有两个相关的推导指南:
template<class InputIterator,
class Compare = less<typename iterator_traits<InputIterator>::value_type>,
class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
set(InputIterator, InputIterator,
Compare = Compare(), Allocator = Allocator())
-> set<typename iterator_traits<InputIterator>::value_type, Compare, Allocator>;
和
template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>>
set(initializer_list<Key>, Compare = Compare(), Allocator = Allocator())
-> set<Key, Compare, Allocator>;
每[over.match.class.deduct]/1:
形成一组函数和函数模板,包括:
在这种情况下,上述推导指南的合成函数和函数模板分别为:
template<class InputIterator,
class Compare = less<typename iterator_traits<InputIterator>::value_type>,
class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
auto __func1(InputIterator, InputIterator,
Compare = Compare(), Allocator = Allocator())
-> set<typename iterator_traits<InputIterator>::value_type, Compare, Allocator>;
和
template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>>
auto __func2(initializer_list<Key>, Compare = Compare(), Allocator = Allocator())
-> set<Key, Compare, Allocator>;
(我使用双下划线表示这些名称是合成的,否则无法访问。)
每[over.match.class.deduct]/2:
按照 [dcl.init] 和 [over.match.ctor]、[over.match.copy] 或 [over.match.list] 中的描述执行初始化和重载解析(根据执行的初始化类型)假设类类型的对象,其中选定的函数和函数模板被认为是该类类型的构造函数,以形成重载集,并且初始化器由执行类模板参数推导的上下文提供. 如果函数或函数模板是从已声明的构造函数或演绎指南explicit生成的,则每个这样的概念构造函数都被认为是显式的。所有这些概念构造函数都被认为是假设类类型的公共成员。
假设的类类型如下所示:
class __hypothetical {
public:
// ...
// #1
template<class InputIterator,
class Compare = less<typename iterator_traits<InputIterator>::value_type>,
class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
__hypothetical(InputIterator, InputIterator,
Compare = Compare(), Allocator = Allocator())
-> set<typename iterator_traits<InputIterator>::value_type, Compare, Allocator>;
// #2
template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>>
__hypothetical(initializer_list<Key>, Compare = Compare(), Allocator = Allocator())
-> set<Key, Compare, Allocator>;
// ...
};
对于 的声明s2,
std::set s2 {a.begin(), a.end()};
重载决议的执行就像在
__hypothetical __hyp{a.begin(), a.end()}; // braces
因此,[over.match.list]进来了。
[...] 重载决议分两个阶段选择构造函数:
构造函数 #2 是一个初始化列表构造函数。函数模板参数推导给出
Key = std::array<int>::iterator
所以推导出的类型s2是
std::set<std::array<int>::iterator>
的声明s2等价于
std::set<std::array<int>::iterator> s2 {a.begin(), a.end()};
因此,s2是一组迭代器,由两个元素组成:a.begin()和a.end()。在您的情况下,std::array<int>::iteratoris 可能int*, and a.begin()anda.end()碰巧分别被序列化为0x7ffecf9d12e0and 0x7ffecf9d12f0。
对于s3,重载决议的执行就像在
__hypothetical __hyp(a.begin(), a.end()); // parentheses
那是直接初始化,并且在[pver.match.ctor]的范围内。构造initializer_list函数无关紧要,而是选择构造函数#1。函数模板参数推导给出
InputIterator = std::array<int>::iterator
所以推导出的类型s3是
set<iterator_traits<std::array<int>::iterator>::value_type>
这是set<int>。因此,声明的s3等价于
std::set<int> s3 (a.begin(), a.end());
s3是一组int从范围初始化的 s [a.begin(), a.end())- 四个元素1, 2, 3, 4,它解释了输出。