2021-12-25

Storing end pointer to uninitialized array in constexpr context

I'm trying to create a constexpr friendly small buffer optimized vector type that stores a begin, end and capacity pointer as usual, but when it is default constructed the begin and capacity pointer point towards local memory before reallocating to heap when required. However I cannot figure out how to store the capacity pointer in the constexpr context, because I want it to be able to support non-trivially constructed types. In order to store non-trivially constructed types I cannot use std::aligned_storage because of the full type erasure which will not allow me to get the elements later (because reinterpret_cast is not allowed), so I decided to store the elements in an array of unions (kind of like optional does it). Storing it like this allows me to get the elements later through union access and allows me to leave the array uninitialized, but i cannot figure out how to store a value pointer to capacity end when it is stored inside of unions because it does not detect the whole one beyond last pointer stuff when pointing to a union value. Ofcourse all of this requires c++20.

#include <algorithm>
#include <memory>
#include <utility>
#include <array>

struct Null{};

template<typename T>
union Storage
{
    Null uninitialized;
    T value;

    constexpr Storage()
    : uninitialized{}
    {}

    template<typename... Args>
    constexpr Storage(Args&&... args)
    : value(std::forward<Args>(args)...)
    {}

    constexpr ~Storage(){}
};

template<typename T, size_t N>
struct Vec
{
    std::array<Storage<T>, N> storage;

    T* begin; 
    T* end;   

    constexpr Vec()
    : begin(makeBegin())
    , end(makeEnd())
    {}

    constexpr T* makeBegin()
    {
        return &storage[0].value;
    }
    constexpr T* makeEnd()
    {
        return (&storage[N].value);
    }
};


constexpr bool test()
{
    Vec<std::pair<float, float>, 10> vec{};

    for(auto it = vec.begin; it < vec.end; ++it)
    {
        std::construct_at(it, 10.0f, 10.0f);
    }

    return vec.begin[5] == std::pair{ 10.0f, 10.0f };
}


int main()
{
    static_assert(test());
}

https://godbolt.org/z/46o19qcvP

Is there another way to get a pointer to stored non-trivially constructible types like pairs in an array without initializing them?



from Recent Questions - Stack Overflow https://ift.tt/3Er0Ddf
https://ift.tt/eA8V8J

No comments:

Post a Comment