Here's my tagged union:
struct UniformVariant
{
enum class UNIFORM_TYPE {FLOAT, INT32, VEC2, VEC3, VEC4, MAT4} type;
union
{
float f;
int i;
glm::vec2 v2;
glm::vec3 v3;
glm::vec4 v4;
glm::mat4 m4;
} value;
};
If I try to use it like so:
void some_function()
{
UniformVariant v;
some_other_function(v);
}
I get a compilation error use of deleted function 'UniformVariant::UniformVariant()'
It further says that it was implicitly deleted because the default definition would be ill-formed. So I've tried adding a constructor to the UniformVariant
UniformVariant() : value(0.0f), type(UNIFORM_TYPE::FLOAT) { };
But similar issues. I believe it has to do with the inclusion of class types in the union; but I can't figure out the syntax to use this correctly.
From a note in [class.union]:
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.
One of the types in that union has a non-trivial default constructor, so you can't default-construct the union. Consider this simpler reproduction:
struct X {
X() { }
};
struct Y {
union {
float f;
X x;
} value;
};
int main()
{
Y y;
}
X
has a non-trivial default constructor, so Y::Y()
is implicitly deleted because the anonymous union default constructor is implicitly deleted.
However, you can just provide your own default constructor for that union:
union U {
U() : f(0.f) { }
float f;
X x;
} value;
And now the example compiles.
However, if you're just implementing your own tagged union, I would highly recommend using Boost.Variant. It's quite useful and solves exactly this problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With