Search code examples
c++operator-overloadingunions

Unnamed union member has non-trivial operator


I am working on a project started back to 1980s, my mission is to substitute the primitive double with the Dummy class I create. The following is the simplified problematic code:

class Dummy{
private:
    double d;
public:
    Dummy(){};
    Dummy(double d1): d{d1}{}; 
    Dummy& operator = ( const Dummy& dm ) {
        d = dm.d;
        return *this;
    }
    Dummy& operator = ( const volatile Dummy& dm ) {
        d = dm.d;
        return *this;
    }
};

struct A{
    bool isDummy;
    union{
        Dummy dm ;
        int i; 
    }B;
};

int main(){
    struct A a1;
    a1.B= 1.1;
    struct A a2;
    a2.B = a1.B;
    return 0;
}

And the following is the error message I got, when I compiled it with x86-64 gcc 11.2:

<source>: In function 'int main()':
<source>:38:14: error: use of deleted function 'A::A()'
   38 |     struct A a1;
      |              ^~
<source>:17:8: note: 'A::A()' is implicitly deleted because the default definition would be ill-formed:
   17 | struct A{
      |        ^
<source>:17:8: error: use of deleted function 'A::<unnamed union>::<constructor>()'
<source>:19:10: note: 'A::<unnamed union>::<constructor>()' is implicitly deleted because the default definition would be ill-formed:
   19 |     union{
      |          ^
<source>:20:15: error: union member 'A::<unnamed union>::dm' with non-trivial 'Dummy::Dummy()'
   20 |         Dummy dm ;
      |               ^~
<source>:40:14: error: use of deleted function 'A::A()'
   40 |     struct A a2;
      |              ^~
<source>:41:15: error: use of deleted function 'A::<unnamed union>& A::<unnamed union>::operator=(const A::<unnamed union>&)'
   41 |     a2.B = a1.B;
      |               ^
<source>:19:10: note: 'A::<unnamed union>& A::<unnamed union>::operator=(const A::<unnamed union>&)' is implicitly deleted because the default definition would be ill-formed:
   19 |     union{
      |          ^
<source>:20:15: error: union member 'A::<unnamed union>::dm' with non-trivial 'Dummy& Dummy::operator=(const Dummy&)'
   20 |         Dummy dm ;
      |               ^~

However when I compiled the original project with g++ 9.3.0, only the problem on the line 41 is reported, which is the problem I want to solve.

I need the overloaded operator to enable copying fromm volatile instances to non-volatile ones for the project.

I have seen the solution here, which is to name the unnamed union and make it a tagged union, but the problem of this solution is that this struct is widely used, if I do it in this way, it will involve too many manual modifications.

I tried to overload operator "=" for the unnamed union with the following code, which doesn't work:

union {
    Dummy dm ;
    int i; 
    void* operator=(const Dummy& d){
        this->dm = d;
        return this;
    };
}B;

How can I solve this problem? Thank you.


Solution

  • Not sure if those modifications are possible for you, but following compiles

    class Dummy
    {
    private:
        double d;
    public:
        Dummy() = default;
        Dummy(double d1): d{d1}{}
        Dummy& operator = ( const Dummy& dm ) = default;
    };
    
    struct A{
        bool isDummy = true;
        union{
            Dummy dm;
            int i;
    
            decltype(auto) operator=(double d) { dm = d; return *this; }
        }B;
    
    };
    

    Demo