6

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:

  1. Is such case (S1, S2) undefined in C++ standard?
  2. 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;
}
timrau
  • 22,578
  • 4
  • 51
  • 64
Midori Yakumo
  • 184
  • 12
  • Why would the copy constructors be deleted? `A` 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!) – Davis Herring Nov 15 '19 at 16:05
  • @DavisHerring A is not trivially copyable/movable for the non-default ~A() implementation, but A is trivially copy/move assignable – Midori Yakumo Nov 18 '19 at 03:21
  • @MidoriYakumo: Sorry, I was sloppy: `A` (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 that `A(xvalue_A)` works, so the union *does* get a defaulted, trivial move constructor. – Davis Herring Nov 18 '19 at 05:37

0 Answers0