std::array - 如何创建无法默认构造的对象的固定大小类成员

问题描述 投票:0回答:1

我正在为任何类型

T
构建一个容器类,它需要保留在编译时长度已知的
T
列表。我正在努力寻找一种可以很好地解决这个问题的数据结构,当我尝试在构造函数体内初始化对象时,
std::array
会抱怨。重要的是,类型
T
不可默认构造。

这是与我正在寻找的功能相对应的片段

#include <array>
#include <cstddef>
#include <type_traits>

struct not_default_constructible
{
    not_default_constructible(int){}
};

static_assert(!std::is_default_constructible_v<not_default_constructible>);

/*
Does not compile!
*/

template<typename T, long N>
struct array_of_ndc
{
    std::array<T,N> arr;

    array_of_ndc(T init)
    {
        for(size_t i = 0; i < N; i++)
        {
            arr[i] = init;
        }
    }
};

此代码片段的问题(无法编译!)是编译器希望我在构造函数主体之前初始化我的

std::array

这是我写的一个解决方案,但感觉就像我在与编译器战斗(它破坏了我喜欢的一切

std::array
,即迭代器),我想看看是否有更多的STL对此的友好解决方案。

template<typename T, long N>
struct no_construction_arr
{
    alignas(T) char data[N * sizeof(T)];

    template<typename U>
        requires(std::constructible_from<T,U>)
    no_construction_arr(U&& init)
    {
        for(size_t i = 0; i < N; i++)
        {
            new (&data[i * sizeof(T)]) T (init);
        }
    }

    T* operator[](size_t index)
    {
        return reinterpret_cast<T*>(&data[index * sizeof(T)]);
    }

    ~no_construction_arr()
    {
        for(size_t i = 0; i < N; i++)
        {
            (reinterpret_cast<T*>(&data[i * sizeof(T)]))->~T();
        }
    }
};

我还要补充一点,我知道我可以用

std::vector
做到这一点。这是关于尝试利用这样一个事实:我提前知道我需要的列表的大小,因此进行不需要的动态分配似乎很浪费。

c++ stdarray
1个回答
2
投票

要获取尚未有要扩展的参数包的序列或重复,请使用

std::make_index_sequence
:

#include <utility>
#include <array>

struct not_default_constructible
{
    not_default_constructible(int){}
};

template<typename T, unsigned long N>
struct array_of_ndc
{
public:
    std::array<T,N> arr;

    explicit array_of_ndc(const T& init)
      : array_of_ndc(init, std::make_index_sequence<N>{})
    {}

private:
    template <std::size_t ...I>
    explicit array_of_ndc(const T& init, std::index_sequence<I...>)
      : arr{ { (static_cast<void>(I), init)... } }
    {}
};
© www.soinside.com 2019 - 2024. All rights reserved.