C++ Logo


Advanced search

Constexpr union array activation

From: D'Alessandro, Luke K <ldalessa_at_[hidden]>
Date: Wed, 8 Sep 2021 18:28:53 +0000

I guess I have two questions:

1. Does std::construct_at change the active member of a union?

I believe it does, via roundabout application of the note in https://eel.is/c++draft/class.union#general-7 (construct_at→equivalent to placement new→activates union members). Is a “note” good enough to support this? Is there somewhere else that makes placement new a valid option? Is “equivalent to” in https://eel.is/c++draft/specialized.construct#2 enough to make the substitution?

2. If 1, can std::construct_at benefit from the logic in https://eel.is/c++draft/class.union#general-6 that begins the lifetime of a nominated member?

My use case for 2 is providing storage for an uninitialized array in constexpr context, e.g., for a statically sized constexpr “vector<T, N>”, that is considered contiguous storage and is not dynamically allocated.

Given some hypothetical struct and union-based constexpr vector storage:

    struct Foo
        constexpr explicit Foo(int) {}

    template <class T, std::size_t N>
    struct Storage
        Foo storage[N];
        constexpr Foo() {} // no active member

I believe https://eel.is/c++draft/class.union#general-6 implies it is possible to start the lifetime of the data array without starting the lifetime of every element in the data array via an **assignment** to an individual element in data.

    constexpr void f()
        Storage<Foo, 2> u;
        u.data[1] = Foo {0};

However given a hypothetical struct without assignment it is not possible.

    struct Bar
        constexpr explicit Bar(int) {}
        constexpr Bar(Bar const&) = delete;
        constexpr Bar(Bar&&) = delete;

    constexpr void g()
        Storage<Bar, 2> u;
        u.data[1] = Bar {0}; // ERROR: use of deleted function

Normally I’d turn to https://eel.is/c++draft/class.union#general-7 and use std::construct_at for Bar type.

    constexpr void h()
        Storage<Bar, 2> u;
        std::construct_at(&u.data[1], 0);

However it’s not at all clear to me that I can apply the logic of https://eel.is/c++draft/class.union#general-6 to activate data via the https://eel.is/c++draft/class.union#general-7 “note” pathway.

gcc currently accepts this code https://godbolt.org/z/n1M9jE8zq however I’m unclear if this is a “feature” or a “bug” , clang is unimpressed with https://eel.is/c++draft/class.union#general-6 in general.


Luke D’Alessandro, Ph.D.
Department of Intelligent Systems Engineering
Indiana University Bloomington

Received on 2021-09-08 13:29:15