8

最近我写了一个非常简单的类。

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;
 }

令我惊喜的是,它编译并正常工作。有人可以向我解释一下编译器如何能够推断出嵌套的大括号初始值设定项用于 astd::pair吗?我正在使用 MSVS 2013。

4

1 回答 1

9
c.AddString({ {"1",1}, {"2", 2}, {"3", 3} });

您正在传递一个花括号初始化列表,它本身包含嵌套的花括号初始化列表AddString. std::initializer_list<std::pair<const char*,int>>如果内部的braced-init-list可以转换为 ,则参数可以匹配参数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 );

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

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

如果初始化列表没有元素并且T有默认构造函数,则省略第一阶段。在复制列表初始化中,如果explicit选择了构造函数,则初始化为 ill-formed

于 2015-05-21T00:37:32.383 回答