解决赋值构造函数 c++ 中的歧义

Resolve ambiguity in assignment constructor c++

提问人:kaisong 提问时间:11/20/2022 最后编辑:Adrian Molekaisong 更新时间:11/20/2022 访问量:100

问:

描述

当存在某个构造函数时,我的代码是模棱两可的。但是,当我注释掉所述构造函数时,编译器会抱怨缺少必要的构造函数。

最小工作示例

struct X;

struct E{
    E(const double& r){ /* important protocol stuff */ }
    E(const X&);
};

struct X{
    X(){ /* important init stuff */ }
    ~X(){ /* important delete stuff */ }
    //X(const double& r){ *this=E(r); }  // POSITION 1
    X(const X& x){ /* important init stuff */ *this=x; }
    X(const E& e){ /* important init stuff */ *this=e; }
    const X& operator=(const X& x){ return *this=E(x); }
    const X& operator=(const E& e){ /* important stuff */ return *this; }
};

E::E(const X& x){ /* important protocol stuff */ }

E operator+(const E& x, const E& y){ /* important protocol stuff */ return E(1); }
E operator*(const E& x, const E& y){ /* important protocol stuff */ return E(2); }

int main(){
    X x,y;
    x = 3.0;
    X u = 4.0;  // POSITION 2
    y = x + u * 5.0;
    X z = 6.0 + 7.0 * y;
}

注释掉位置 1 后,位置 2 将抛出错误。

包含位置 1 时,存在歧义错误。

基本上,我想删除位置 1,并通过双 >E->X 投射双>X。

问题

  1. 问题的名称是什么?
  2. 我该如何解决?

我尝试过的事情:

  • 显式关键字在各种构造函数前面。对于 E,这会导致位置 2 之后出现错误。对于 X,这会导致与注释掉位置 1 相同的错误。
  • 从 X,E 的定义中删除构造函数/运算符。然而,这不是解决方案,因为我需要能够包含一些重要的东西
  • 尝试不同的编译器(G++ 8.3.0 和 9.2.0、Clang++ 12.0.0)。这并没有改变问题。
C G++ LLVM 模棱两可

评论

0赞 molbdnilo 11/20/2022
请比“抛出错误”更具体。复制并粘贴实际的错误消息。
0赞 molbdnilo 11/20/2022
在隐式转换链中只能有一个用户定义的隐式转换。

答:

5赞 Adrian Mole 11/20/2022 #1

出现歧义是因为(在行中)编译器无法决定使用两个赋值运算符中的哪一个:带有参数的运算符或带有 的赋值运算符,因为这两种参数类型都可以从给定的参数类型转换(因为两者都具有采用参数的构造函数)。x = 3.0;X&E&doubleEXconst double&

您可以通过提供第三个赋值运算符来解决此错误,该运算符采用参数,如下所示:const double&

struct X {
    X() { /* important init stuff */ }
    ~X() { /* important delete stuff */ }
    X(const double& r){ *this=E(r); }  // Now uncommented (required)
    X(const X& x) { /* important init stuff */ *this = x; }
    X(const E& e) { /* important init stuff */ *this = e; }
    const X& operator=(const double& x) { return *this = E(x); } // Add this!
    const X& operator=(const X& x) { return *this = E(x); }
    const X& operator=(const E& e) { /* important stuff */ return *this; }
};