I am trying to compile the following tagged union in a c++ file and I am running into issues. Could someone explain what I am missing or what I have to change to get the following to work? I have tried looking this up online and unfortunately have gotten nowhere...
#include <string>
using std::string;
#include <iostream>
using std::cout;
using std::endl;
#include <new>
const int TU_STRING = 0;
const int TU_INT = 1;
const int TU_FLOAT = 2;
struct TU {
int type;
union {
int i;
float f;
std::string s;
} u;
TU(const TU& tu) : type(tu.type) {
switch (tu.type) {
case TU_STRING: new(&u.s)(tu.u.s); break;
case TU_INT: u.i = tu.u.i; break;
case TU_FLOAT: u.f = tu.u.f; break;
}
}
~TU() {
if (tu.type == TU_STRING)
u.s.~string();
}
};
int main() {
TU tu;
return 0;
}
I am compiling with clang using the following command
g++ -std=c++14 some.cpp
and I am getting lots of compiling errors
some.cpp:18:4: error: call to implicitly-deleted default constructor of 'union (anonymous union at some.cpp:12:4)'
TU(const TU& tu) : type(tu.type) {
^
some.cpp:15:18: note: default constructor of '' is implicitly deleted because variant field 's' has a non-trivial default constructor
std::string s;
^
some.cpp:18:4: error: attempt to use a deleted function
TU(const TU& tu) : type(tu.type) {
^
some.cpp:15:18: note: destructor of '' is implicitly deleted because variant field 's' has a non-trivial destructor
std::string s;
^
some.cpp:20:13: error: use of undeclared identifier 'TU_STRING'
case TU_STRING: new(&u.s)(tu.u.s); break;
^
some.cpp:20:34: error: unknown type name 'tu'
case TU_STRING: new(&u.s)(tu.u.s); break;
^
some.cpp:20:36: error: expected ')'
case TU_STRING: new(&u.s)(tu.u.s); break;
^
some.cpp:20:33: note: to match this '('
case TU_STRING: new(&u.s)(tu.u.s); break;
^
some.cpp:21:13: error: use of undeclared identifier 'TU_INT'
case TU_INT: u.i = tu.u.i; break;
^
some.cpp:22:13: error: use of undeclared identifier 'TU_FLOAT'
case TU_FLOAT: u.f = tu.u.f; break;
^
some.cpp:26:10: error: use of undeclared identifier 'tu'
if (tu.type == TU_STRING)
^
some.cpp:26:21: error: use of undeclared identifier 'TU_STRING'
if (tu.type == TU_STRING)
^
some.cpp:25:4: error: attempt to use a deleted function
~TU() {
^
some.cpp:15:18: note: destructor of '' is implicitly deleted because variant field 's' has a non-trivial destructor
std::string s;
^
some.cpp:32:8: error: no matching constructor for initialization of 'TU'
TU tu;
^
some.cpp:18:4: note: candidate constructor not viable: requires single argument 'tu', but no arguments were provided
TU(const TU& tu) : type(tu.type) {
^
11 errors generated.
Thanks!
EDIT: Updated code which still doesnt work
struct VariantType {
enum class Tag {INTEGER, STRING};
Tag tag;
union TypeUnion {
string inner_string;
int inner_int;
TypeUnion(const std::string& str) {
new(&inner_string) string(str);
}
TypeUnion(int inner_int_in) {
inner_int = inner_int_in;
}
TypeUnion(std::string other) : inner_string{std::move(other)} {}
} type_union;
VariantType(const std::string& str) : tag{Tag::STRING} {
new(&this->type_union.inner_string) string(str);
}
VariantType(int inner_int_in) : tag{Tag::INTEGER} {
this->type_union.inner_int = inner_int_in;
}
};