The following code gives different compilation result with g++ 7.3 and clang++ 7.0, but to my knowledge all of copy constructor of S1, S2, S3 is deleted and none of the instantiation should success.
Question:
- Is such case (S1, S2) undefined in C++ standard?
- What is the difference between anonymous union without constructor/destructor implementation and named union with default constructor/destructor?
template <typename T>
struct S1
{
union
{
T payload;
};
S1() {}
~S1() {}
};
template <typename T>
struct S2
{
union
{
T payload;
};
S2() {}
virtual ~S2() {}
};
template <typename T>
struct S3
{
union U
{
T payload;
U() = default;
~U() = default;
} storage;
S3() {}
~S3() {}
};
#include <iostream>
struct A // overloaded A() & ~A()
{
A()
{
std::cout << "A()" << std::endl;
}
~A()
{
std::cout << "~A()" << std::endl;
}
};
int main()
{
{
S1<A> a;
auto b = a; // g++ OK, clang++ OK
}
{
S2<A> a;
auto b = a; // g++ fail, clang++ OK
}
{
S3<A> a;
auto b = a; // g++ fail, clang++ fail
}
return 0;
}
S1<A>
andS2<A>
are both copy/move-constructible, whileS3<A>
is not. Weird. – SumerlinA
is trivially copyable/movable, so all the unions get a copy and a move constructor that are themselves trivial. (Also, what is the error? This isn’t about undefined behavior at runtime!) – WorkbagA
(and thence each union containing it) gets a trivial copy constructor (deprecatedly, despite the user-provided destructor) but is not trivially copyable. It gets no move constructor at all, but is still “movable” in thatA(xvalue_A)
works, so the union does get a defaulted, trivial move constructor. – Workbag