【问题标题】:std::initializer_list type deductionstd::initializer_list 类型推导
【发布时间】:2015-08-02 10:47:34
【问题描述】:

最近写了一个很简单的类。

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。

【问题讨论】:

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


    【解决方案1】:
    c.AddString({ {"1",1}, {"2", 2}, {"3", 3} });
    

    您正在传递一个 braced-init-list,它本身包含嵌套的 brace-init-listAddString。如果内部 braced-init-list 可以转换为 std::pair&lt;const char*,int&gt;,则该参数可以匹配 std::initializer_list&lt;std::pair&lt;const char*,int&gt;&gt; 参数。

    这个重载解决过程分两步进行;首先尝试匹配带有std::initializer_list 参数的std::pair 的构造函数。由于std::pair 没有这样的构造函数,所以进行第二步,将std::pair&lt;const char*,int&gt; 的其他构造函数以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 构造函数,则初始化格式错误

    【讨论】:

    • 很好的答案,更完整!
    • 谢谢,这澄清了一些事情。当涉及到大括号初始化列表时,我需要更多地了解过载解决方案。
    • @pebbleonthebeach 涉及列表初始化时的重载解决规则是我在上面复制粘贴的。如果您的意思是您需要熟悉一般的重载解析,我建议您从this video 开始(如果有时间,请观看整个系列)。
    猜你喜欢
    • 2014-05-08
    • 2012-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多