C++ Logo

std-proposals

Advanced search

Uninitialized array storage in constexpr context cannot provide contiguous iterators

From: D'Alessandro, Luke K <ldalessa_at_[hidden]>
Date: Wed, 4 Nov 2020 18:03:49 +0000
This is something that I’ve run into while developing my own constexpr-compatible vector implementation with support for non-default-constructible value_types. It’s way outside of my wheelhouse to know how to fix this, but I wanted to make sure the community is aware and see if someone wants to take up the challenge.

Consider that non-constexpr uninitialized array storage is straightforward to obtain and use via byte-array allocation, reinterpret_cast, and placement new/delete, as example the (not-std) vector implementation below.

template <typename T, std::size_t N>
struct non_constexpr_vector
{
    std::byte storage[sizeof(T) * N];
    // … manage storage appropriately

    const T* begin() const {
        return reinterpret_cast<const T*>(array);
    }
};

Now consider that constexpr uninitialized array storage may not use reinterpret_cast, but is still straightforward to obtain and use via union allocation and construct_at/destroy_at as of C++20 (modulo compiler conformance).

template <typename T, std::size_t N>
struct constexpr_vector
{
    union { T t; } storage[N];
    // … manage storage appropriately

    struct iterator {
        // … access to active T’s in storage
    };

    constexpr iterator begin() const {
        return {}; // whatever your iterator wants
    }
};

The non-constexpr iterator type (raw pointer) can model contiguous integrator, while I do not believe there is any way that the constexpr iterator can do the same thing. This same behavior appears in the obvious dynamic-capacity version, but feels less immediate as they will not currently appear as top-level constexpr objects (my use case was attempting to initialize a string_view with the results of a constexpr computation).

I don’t have the slightest idea where to even start addressing this issue.

Two options that came to mind.

1. Some library-based uninitialized_storage<T> type that would bypass the use of union and model this situation directly (continuing to use construct_at/destroy_at).

2. Some special casing for array objects of unions with one non-static data member that would allow allow [expr.add] to function as needed to model contiguous iterator for a pointer to the member.

Does this feel like a real issue worth pursuing? Does it already have some solution in the works?

Luke

----
Luke D’Alessandro, Ph.D.
Department of Intelligent Systems Engineering
Indiana University Bloomington
ldalessa_at_[hidden]<mailto:ldalessa_at_[hidden]>


Received on 2020-11-04 12:06:06