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

时间:2022-04-03 23:57:36

I encounter an issue, that is hard to explain for me. Here is the minimal, reproducible code, that is failing on both GCC 6.2 and Clang 3.9:

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

Note that I didn't write the specific constructor to convert from T1 to T2, so I guess it should be all clear to the compiler, that the only way is to use user defined cast operator.

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

The curious fact is that when I comment out a seemingly unrelated cast operator:

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

// operator int() { return field1; }

then the code compiles hassle-free. What is the reason for that?

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

1 个解决方案

#1


3  

(T2) obj1 means exactly the same thing as T2(obj1) (or static_cast<T2>(obj1) in this case), but maybe it'll be easier to reason about this constructor-like syntax.

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

With the code as-is, there are two options:

代码按原样,有两种选择:

  • construct T2 with an int, obtained by the user-defined conversion operator to int
  • 使用int构造T2,由用户定义的转换运算符获取到int
  • construct T2 from T2 obtained by the user-defined conversion operator to T2
  • 从用户定义的转换运算符到T2获得T2的T2

As per N4140:

根据N4140:

If there is exactly one viable function that is a better function than all other viable functions, then it is the one selected by overload resolution; otherwise the call is ill-formed

如果只有一个可行的函数比所有其他可行函数更好的函数,则它是由重载决策选择的函数;否则电话会形成不良

Two implicit conversion sequences of the same form are indistinguishable conversion sequences unless one of the following rules applies:

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

  • User-defined conversion sequence U1 is a better conversion sequence than another user-defined conversion sequence U2 if they contain the same user-defined conversion function or constructor or they initialize the same class in an aggregate initialization and in either case the second standard conversion sequence of U1 is better than the second standard conversion sequence of U2.
  • 用户定义的转换序列U1是比另一个用户定义的转换序列U2更好的转换序列,如果它们包含相同的用户定义的转换函数或构造函数,或者它们在聚合初始化中初始化相同的类,并且在任何一种情况下都是第二个标准转换序列U1优于U2的第二标准转换序列。

Since this doesn't apply, neither conversion is better than the other.

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

#1


3  

(T2) obj1 means exactly the same thing as T2(obj1) (or static_cast<T2>(obj1) in this case), but maybe it'll be easier to reason about this constructor-like syntax.

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

With the code as-is, there are two options:

代码按原样,有两种选择:

  • construct T2 with an int, obtained by the user-defined conversion operator to int
  • 使用int构造T2,由用户定义的转换运算符获取到int
  • construct T2 from T2 obtained by the user-defined conversion operator to T2
  • 从用户定义的转换运算符到T2获得T2的T2

As per N4140:

根据N4140:

If there is exactly one viable function that is a better function than all other viable functions, then it is the one selected by overload resolution; otherwise the call is ill-formed

如果只有一个可行的函数比所有其他可行函数更好的函数,则它是由重载决策选择的函数;否则电话会形成不良

Two implicit conversion sequences of the same form are indistinguishable conversion sequences unless one of the following rules applies:

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

  • User-defined conversion sequence U1 is a better conversion sequence than another user-defined conversion sequence U2 if they contain the same user-defined conversion function or constructor or they initialize the same class in an aggregate initialization and in either case the second standard conversion sequence of U1 is better than the second standard conversion sequence of U2.
  • 用户定义的转换序列U1是比另一个用户定义的转换序列U2更好的转换序列,如果它们包含相同的用户定义的转换函数或构造函数,或者它们在聚合初始化中初始化相同的类,并且在任何一种情况下都是第二个标准转换序列U1优于U2的第二标准转换序列。

Since this doesn't apply, neither conversion is better than the other.

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