初始化中模板转换运算符类型推导的规则是什么?

时间:2017-04-15 23:19:17

标签: c++ templates language-lawyer conversion-operator

考虑以下代码:

struct S
{
    template <typename T>
    operator T() const
    { return {}; }
};

struct R
{
    R() = default;
    R(const R&) = default;
    R(R&&) = default;
    R(bool) {}
};

standard上的哪些是为以下行为定义的规则?

S s;
R r1 = s; // (1) passes: T = R
R r2(s);  // (2) ambiguity: T = R or bool?

为什么没有(1)引起歧义问题(假设R也可以bool初始化)?我最近为一个类似的问题写了一个答案,但我很好奇为什么(1)在这种情况下不像(2)那样,我不知道它在哪里在标准上描述了。

1 个答案:

答案 0 :(得分:2)

8.5 / 15-16:

  

调用大括号或等于初始化程序条件=形式的初始化以及... 副本初始化

     

表单中出现的初始化

T x(a);
T x{a};
  

以及......被称为直接初始化

因此R r1 = s;是复制初始化,R r2(s);是直接初始化。关于第17段:

  
      
  • 如果目标类型是(可能是cv限定的)类类型:

         
        
    • 如果初始化是直接初始化,或者它是复制初始化,其中源类型的cv-nonqualified版本与目标类的构造函数相同,或者是派生类,构造函数被考虑。列举了适用的构造函数(13.3.1.3),并通过重载解析(13.3)选择最佳构造函数。

    •   
    • 否则(即,对于剩余的复制初始化情况),可以从源类型转换为目标类型或(当使用转换函数时)到其派生类的用户定义的转换序列是按照13.3.1.4的描述进行枚举,最好的一个是通过重载决议(13.3)选择的。

    •   
  •   

因此,直接初始化会查看R的所有构造函数并最终变得模糊,而复制初始化显式尝试直接将表达式转换为R并成功。