struct anonymous untagged union error attempting to reference a deleted function

173 views Asked by At

Recently, I try to convert my VS2008 c++ project to VS2019, because need to update libray, support etc, I have snippet, compiled on VS2008 but not with vs2019

struct A
{
  WORD insideA;
  A(): insideA(0)
  {}

  ~A(){}

}

struct B
{
  WORD insideB;
  B():insideB(0)
  {}

  ~B(){}
}

struct AB
{
  union
  {
    struct { A dataA; };
    struct 
    {
      WORD wX;
      B dataB;
    } 
  }
  
  AB()
    :wX(0)
  {}

}

struct USAGE
{
    AB usageAB;
    USAGE(AB &parAB)
      : usageAB(parAB) //<< attempting to reference a deleted function
    {}
}

Is there any standard changes with anonymous union between vs2008 and vs2019?

1

There are 1 answers

0
Jeroen Lammertink On

Your code was missing some semicolons here and there, and the union was missing member names. I've made a few changes of which I hope that the code still reflects your case. Yes, there were standard changes with respect to unions: before C++11, union member with non-trivial constructors were not allowed. From 11 onwards they are, but then the union must also provide a constructor. So, I guess that your code did compile under vs2008 due to a non-standard language extension of MS.

What you need, to get your code going, is a destructor which calls the appropriate destructor of the constructed union member. Then you must know, which member was constructed. I've solved that below by adding an m_which member of enum class which_t.

Another solution is getting rid of the destructors ~A() and ~B().

You may also consider using std::variant, which is in the standard library from C++17 onwards. It can replace many uses of unions and union-like classes.

using WORD = unsigned short;

//////////////////////////////////////////////////////////////////////

struct A
{
    WORD insideA;
    explicit A(WORD x) : insideA(x)
    {}
    ~A() {}
};

struct B
{
    WORD insideB;
    explicit B(WORD x) :insideB(x)
    {}
    ~B() {}
};

enum class which_t
{
    dataA,
    dataB,
    wX
};

struct AB
{
    union
    {
        A dataA;
        B dataB;
        WORD wX;
    };
    which_t m_which;
    AB(A const& a) // maybe you wanna leave out 'explicit' here
        : dataA(a)
        , m_which(which_t::dataA)
    {}
    AB(B const& b) // maybe you wanna leave out 'explicit' here
        : dataB(b)
        , m_which(which_t::dataB)
    {}
    AB(WORD x) // maybe you wanna leave out 'explicit' here
        : wX(x)
        , m_which(which_t::wX)
    {}
    ~AB()
    {
        switch (m_which)
        {
        case which_t::dataA:
            dataA.~dataA();
            break;
        case which_t::dataB:
            dataB.~dataB();
            break;
        case which_t::wX:
            break;
        }
    }
};

struct USAGE
{
    AB usageAB;
    explicit USAGE(AB& parAB)
        : usageAB(parAB) //<< attempting to reference a deleted function
    {}
};

//////////////////////////////////////////////////////////////////////

int main()
{
    AB ab1(A{ 1 });
    USAGE usage1(ab1);
    AB ab2(B{ 2 });
    USAGE usage2(ab2);
    AB ab3(3);
    USAGE usage3(ab3);
}