0

I have the following code:

struct Foo
{
    int type;
    union
    {
        int intValue;
        double doubleValue;
        std::wstring stringValue;
    } value;
};

and then in the cpp file I have:

std::vector<Foo> row;
some_class_object->func( row );

and I got:

error C2280: 'void *Foo::__delDtor(unsigned int)': attempting to reference a deleted function 

What is the problem here?

EDIT:

So I added this destructor:

~Foo()
{
    if( type ==3 )
        value.stringValue.~std::wstring();
}

and I got an error:

error C2061: syntax error: identifier 'wstring'.

Apparently std::string vs std::wstring matter in this case...

Didn't know about that.

EDIT2:

I am now getting:

 error C2280: 'Foo::<unnamed-type-value>::~<unnamed-type-value>(void)': attempting to reference a deleted function
Igor
  • 5,620
  • 11
  • 51
  • 103
  • Use `union` only to implement `variant`, then use it. Boost provides one for pre-C++17, std provides since C++17. – Jarod42 Mar 05 '21 at 09:34

2 Answers2

5

The union contains a member (std::string) with a non-trivial destructor. This means that the union can't have a defaulted destructor (it wouldn't know which member's destructor to call). So you need to provide a custom destructor.

In your case define a union destructor that does nothing and then do the work in the struct destructor:

struct Foo {
    int type;

    union U {
        int intValue;
        double doubleValue;
        std::wstring stringValue;

        
        ~U() noexcept {}

    } value;

    ~Foo()
    {
        using std::wstring;

        if (type == 3)
            value.stringValue.~wstring();
    }
};

Please note that you need to do this for copy/move constructor/assignments as well.

In C++17 you have std::variant which is a safe union.

bolov
  • 72,283
  • 15
  • 145
  • 224
  • so how do I write it? I am not using pointers, just a plain members.And I'm not there yet - I don't have C++17 compilers across platforms... – Igor Mar 05 '21 at 04:35
  • 2
    @Igor "*so how do I write it?*" - see [Is a Union Member's Destructor Called](https://stackoverflow.com/questions/40106941/) – Remy Lebeau Mar 05 '21 at 04:44
  • @RemyLebeau, I updated the OP with the code I tried and the error I got. – Igor Mar 05 '21 at 05:48
  • @Igor drop the `std::`, it is not part of the destructor's name: `value.stringValue.~wstring();` Just make sure you had used `new(&value.stringValue) wstring();` beforehand – Remy Lebeau Mar 05 '21 at 05:53
  • @Igor `using std::wstring; value.stringValue.~wstring();` – bolov Mar 05 '21 at 05:54
  • @bolov, I edited an OP with the new error. – Igor Mar 05 '21 at 06:48
0

THE UNION has destructor deleted and you're attempting to use it as anonymous entity. You can't define destructor there without naming the type.

struct Foo
{
    int type;
    union ValueType
    {
        int intValue;
        double doubleValue;
        std::wstring stringValue;
        ~ValueType() {}
    } value;
    ~Foo();
};

Foo::~Foo()
{
    if( type ==3 )
        value.stringValue.std::wstring::~wstring();
}

It's far better to use standard tagged union template provided with compiler instead of rolling your own because of arcane code like this.

Swift - Friday Pie
  • 12,777
  • 2
  • 19
  • 42