使用显式用户定义的强制转换操作符调用函数是不明确的

时间:2016-11-02 12:38:31

标签: c++ casting

我遇到了一个问题,这对我来说很难解释。这是最小的,可重现的代码,它在GCC 6.2和Clang 3.9上都失败了:

class T2;

class T1
{
    int field1;
public:
    T1(int pf) : field1(pf) {}
    operator int() { return field1; }
    operator T2();
};

class T2
{
    int field2;
public:
    T2(int pf) : field2(pf) {} 
};

T1::operator T2() { return T2(field1); }

void foo(T2 pt) {}

int main()
{
    T1 obj1(1);
    T2 obj2(2);

    foo((T2) obj1);             // ambiguous conversion for C-style cast from 'T1' to 'T2'
    foo(T2(obj1));              // ambiguous conversion for functional-style cast from 'T1' to 'T2'
    foo(static_cast<T2>(obj1)); // ambiguous conversion for static_cast from 'T1' to 'T2'
}

请注意,我没有编写特定的构造函数来从T1转换为T2,所以我想编译器应该都清楚,唯一的方法是使用用户定义的强制转换操作符。

奇怪的事实是,当我评论出一个看似无关的演员:

// operator int() { return field1; }

然后代码编译无忧无虑。这是什么原因?

1 个答案:

答案 0 :(得分:3)

(T2) obj1T2(obj1)(或本例中为static_cast<T2>(obj1))完全相同,但也许它更容易推理出类似构造函数的语法。< / p>

代码按原样,有两个选项:

  • 使用T2构建int,由用户定义的转换运算符获取int
  • T2构建T2,由用户定义的转换运算符获取T2

根据N4140:

  

如果只有一个可行的功能比一个更好的功能   所有其他可行的功能,然后它是由重载选择的功能   解析度;这个电话是不正确的

     

两个相同形式的隐式转换序列   除非下列之一,否则无法区分转换序列   规则适用:

     
      
  • 用户定义的转换序列U1是一个比其他用户定义的转换序列U2更好的转换序列   包含相同的用户定义转换函数或构造函数或   他们在聚合初始化和初始化中初始化相同的类   无论哪种情况,U1的第二标准转换序列都更好   比U2
  • 的第二个标准转换序列   

由于这不适用,因此两种转换都不比另一种好。