0

This question from me solves the problem nicely.

However, it looks like I will need to create a constructor for that structure, because the following code:

std::vector<Foo> row;
row.push_back( Foo( 1, 1 ) );

errors out.

When I tried to add the constructor

Foo(int mytype, int myvalue)
{
    type = mytype;
    value.intvalue = myvalue;
}

it errors out saying

attempting to reference a deleted function

Do I need to define all 3 constructors?

Or there is something else?

TIA!!

Igor
  • 5,620
  • 11
  • 51
  • 103
  • In [This](https://stackoverflow.com/questions/66486453/referencing-deleted-destructor#66486453) question, you didn't accept any answer. However, the [answer with most votes](https://stackoverflow.com/a/66486532/7478597) recommends to use a [std::variant](https://en.cppreference.com/w/cpp/utility/variant). This would make all your fiddling with these ugly `union` obsolete... `union` are an in-heritage of C and don't play well with classes in C++. So, why all the trouble? – Scheff's Cat Mar 09 '21 at 06:26
  • @Scheff, std::variant is C++17. I'm still on C++11. – Igor Mar 09 '21 at 06:35
  • OK. I overlooked the [c++11] - my fault. However, even if this is a follow-up question, please provide a [mcve]. Your `union` probably is missing something essential and I cannot see what (without code). – Scheff's Cat Mar 09 '21 at 06:40
  • boost (and other C++11 compatible libraries) has variant type. – Jarod42 Mar 09 '21 at 08:34

1 Answers1

1

A cite borrowed from this even older answer:

The standard states in [class.union]/2

A union can have member functions (including constructors and destructors), but not virtual (10.3) functions. A union shall not have base classes. A union shall not be used as a base class. If a union contains a non-static data member of reference type the program is ill-formed. At most one non-static data member of a union may have a brace-or-equal-initializer . [ Note: If any non-static data member of a union has a non-trivial default constructor (12.1), copy constructor (12.8), move constructor (12.8), copy assignment operator (12.8), move assignment operator (12.8), or destructor (12.4), the corresponding member function of the union must be user-provided or it will be implicitly deleted (8.4.3) for the union. — end note ]

emphasis mine

So, what OP did for the destructor might be necessary for constructor (and, maybe, assignment operator) as well.

Here, the enhanced example of OP with constructors:

#include <iostream>  
#include <string>

struct Value {
    int type;

    union Data {
        int intValue;
        double doubleValue;
        std::string stringValue;
        
        Data(int value): intValue(value) { }
        Data(double value): doubleValue(value) { }
        Data(const std::string &value): stringValue(value) { }
        ~Data() noexcept { }
    } data;

    Value(int value): type(1), data(value) { }
    
    Value(double value): type(2), data(value) { }

    Value(const std::string &value): type(3), data(value) { }
    
    ~Value()
    {
        using std::string;
        if (type == 3) data.stringValue.~string();
    }
};

int main()  
{
  { Value value(123);
    std::cout << "value: " << value.type << ": '" << value.data.intValue << "'\n";
  }
  { Value value(1.23);
    std::cout << "value: " << value.type << ": '" << value.data.doubleValue << "'\n";
  }
  { Value value(std::string("Hello world"));
    std::cout << "value: " << value.type << ": '" << value.data.stringValue << "'\n";
  }
}

Output:

value: 1: '123'
value: 2: '1.23'
value: 3: 'Hello world'

Live Demo on coliru

Scheff's Cat
  • 19,528
  • 6
  • 28
  • 56