std :: initializer_list类型扣除

时间:2015-05-21 00:02:06

标签: c++ c++11 initializer-list type-deduction list-initialization

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

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

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

1 个答案:

答案 0 :(得分:9)

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

您正在传递 braced-init-list ,它本身包含嵌套的 brace-init-list AddString。如果内部 braced-init-list 可以转换为std::initializer_list<std::pair<const char*,int>>,则参数可以匹配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)时,重载决策分两个阶段选择构造函数:
   - 最初,候选函数是类T的初始化列表构造函数(8.5.4),参数列表由初始化列表作为单个参数组成。
   - 如果找不到可行的初始化列表构造函数,则再次执行重载解析,其中候选函数是类T 的所有构造函数,参数列表包含初始化列表。

     

如果初始化列表没有元素且T具有默认构造函数,则省略第一个阶段。 在复制列表初始化中,如果选择了explicit构造函数,则初始化格式错误