std :: initializer_list类型扣除

peb*_*ach 8 c++ initializer-list c++11 list-initialization type-deduction

最近我写了一个非常简单的课.

class C
{
public:
    void AddString(std::initializer_list<std::pair<const char*,int>> x)
    {
          //irrelevant
    }
};

int main()
 {
           C c;
           c.AddString({ {"1",1}, {"2", 2}, {"3", 3} });
           .... //other unimportant stuff
           return 0;
 }
Run Code Online (Sandbox Code Playgroud)

令我惊喜的是,它编译并正常工作.有人可以向我解释一下编译器如何能够推断出嵌套的支撑初始化器是为了std::pair什么?我正在使用MSVS 2013.

Pra*_*ian 9

c.AddString({ {"1",1}, {"2", 2}, {"3", 3} });
Run Code Online (Sandbox Code Playgroud)

你传递一个支撑,初始化列表,它本身包含嵌套的大括号初始化列表 s到AddString.std::initializer_list<std::pair<const char*,int>>如果可以将内部braced-init-list s转换为,则参数可以匹配参数std::pair<const char*,int>.

这个过载分辨过程分两步进行; 首先试图匹配的建设者std::pair采取该std::initializer_list说法.由于std::pair没有这样的构造函数,所以第二步发生,其中其他构造函数std::pair<const char*,int>char const[2]int作为参数枚举.这将匹配以下pair构造函数,因为它char const[2]可以隐式转换为char const *构造函数本身explicit.

template< class U1, class U2 >
constexpr pair( U1&& x, U2&& y );
Run Code Online (Sandbox Code Playgroud)

引用N3337§13.3.1.7 / 1 [over.match.list]

当非聚合类类型的对象T被列表初始化(8.5.4)时,重载决策分两个阶段选择构造函数:
- 最初,候选函数是类的初始化列表构造函数(8.5.4)T和参数list包含初始化列表作为单个参数.
- 如果找不到可行的初始化列表构造函数,则再次执行重载解析,其中候选函数是类的所有构造函数,T参数列表由初始化列表的元素组成.

如果初始化列表没有元素并且T具有默认构造函数,则省略第一个阶段.在copy-list-initialization中,如果explicit选择了构造函数,则初始化是错误的.