constexpr 类型化非动态未初始化存储

Vai*_*Man 6 c++ c++20

在 C++20 中,我们有

constexpr T* std::allocator<T>::allocate( std::size_t n );
Run Code Online (Sandbox Code Playgroud)

在编译时分配类型化动态未初始化存储(并construct_at构造对象)。

但是我们在编译时是否有类型的非动态存储,例如类型化的 aligned_storage


编辑:一种有用的用法是实现 constexpr static_vector:

template<class T, size_t Cap>
class static_vector {
    size_t size;
    Storage<T, Cap> storage;
};
Run Code Online (Sandbox Code Playgroud)

LB-*_*B-- 2

是的,您可以使用std::array<std::optional<T>, Cap>,或者union如果您不希望数组中每个值都有自己的布尔值的开销,则可以使用 a 自己实现它。C++17 使我们能够在constexpr尚无活动成员时激活联合成员,而 C++20 允许我们在constexpr遵循正确的对象生存期规则的情况下更改活动成员。请注意,激活成员或更改哪个成员处于活动状态的方法很少union- 特别是,您不能使用指向成员的指针语法来激活联合成员

这是该方法的示例unionhttps://gcc.godbolt.org/z/h6djsYshr

#include <cstddef>
#include <memory>
#include <new>
#include <type_traits>
#include <utility>

namespace example
{
    struct None {};
    template<class T, std::size_t Cap>
    struct Storage
    {
        union U
        {
            None none;
            T some;
            constexpr U() noexcept : none{} {}
        };
        U values[Cap];
    };
    template<class T, std::size_t Cap>
    class static_vector
    {
        std::size_t size{};
        Storage<T, Cap> storage;
    public:
        constexpr ~static_vector() noexcept
        {
            for(std::size_t i = 0; i < size; ++i)
            {
                std::destroy_at(&storage.values[i].some);
            }
        }
        template<typename... Args>
        constexpr T& emplace_back(Args&&... args)
        {
            if(size >= Cap)
            {
                throw std::bad_alloc();
            }
            auto& u{storage.values[size]};
            std::construct_at(&u.some, std::forward<Args>(args)...);
            ++size;
            return u.some;
        }
    };
}
namespace example_usage
{
    struct CounterHolder
    {
        int& counter;
        constexpr CounterHolder(int& counter_) noexcept
        : counter{counter_}
        {
        }
    };
    [[nodiscard]] constexpr int demo() noexcept
    {
        example::static_vector<CounterHolder, 10> v;
        int counter{};
        ++v.emplace_back(counter).counter;
        ++v.emplace_back(counter).counter;
        ++v.emplace_back(counter).counter;
        return counter;
    }
    static constexpr int const demoResult{demo()};
    [[nodiscard]] int showDemoResultInAssembly() noexcept
    {
        return demoResult;
    }
}
Run Code Online (Sandbox Code Playgroud)