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

Calling function with explicit user defined cast operator is ambigous

本文关键字:运算符 转换 调用 函数 不明确 用户 定义      更新时间:2023-10-16

我遇到了一个问题,这对我来说很难解释。以下是最小的、可重现的代码,在 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; }

然后代码编译起来很麻烦。这是什么原因呢?

(T2) obj1的意思与T2(obj1)完全相同(在这种情况下为static_cast<T2>(obj1)(,但也许更容易推理这种类似构造函数的语法。

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

  • int构造T2,由用户定义的转换算子得到int
  • 根据用户定义的转换运算符获得的T2构造T2 T2

根据 N4140:

如果只有一个可行的函数比 所有其他可行的函数,那么它是重载选择的函数 分辨率;否则调用格式不正确

相同形式的两个隐式转换序列是 无法区分的转换序列,除非符合以下条件之一 规则适用:

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

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