C++ Logo


Advanced search

Re: Anonymous unions with non-trivial member types

From: Andrew Schepler <aschepler_at_[hidden]>
Date: Sat, 29 Aug 2020 13:02:07 -0400
On Fri, Aug 28, 2020 at 7:36 AM Yongwei Wu via Std-Discussion <
std-discussion_at_[hidden]> wrote:

> ...
> struct StringIntChar {
> enum { String, Int, Char } type;
> ~StringIntChar()
> {
> if (type == String) {
> string_value.~string();
> }
> }
> union {
> string string_value;
> int int_value;
> char char_value;
> };
> };
> ...

 I do see an issue here with the Standard wording. It appears the intent
was to allow code like this, but I think by a strict reading, the
~StringIntChar destructor is ill-formed.

The anonymous union type has a destructor which is implicitly declared as
deleted. For any other special member function, this deleted member isn't
necessarily a problem for the containing class StringIntChar, since a
user-defined special member just won't call the member of the anonymous
union. But for destructors, [class.dtor]/14 says

After executing the body of the destructor and destroying any objects with
> automatic storage duration allocated within the body, a destructor for
> class X calls the destructors for X's direct non-variant non-static data
> members, the destructors for X's non-virtual direct base classes and, if X
> is the most derived class ([class.base.init]), its destructor calls the
> destructors for X's virtual base classes.

I think the "non-variant" phrasing reflects an intent to make code like the
example valid. But the subobject whose type is the anonymous union is still
a "direct non-variant non-static data member" of StringIntChar, so any
StringIntChar destructor still involves a call to the union's deleted
destructor, and so is ill-formed.

Worth a Defect Report, does anyone think?

-- Andrew Schepler

Received on 2020-08-29 12:05:48