使用非平凡的构造函数初始化 std::array 个对象

Initialize an std::array of objects with non-trivial constructor

我有一个 class 定义为

class Edgelet
{
private:
    const int e_size;
    //Other private members...
public:
    //The constructor
    explicit Edgelet (int size, Color cl1 = Color::NA, Color cl2 = Color::NA);
    //Other public members...

因为 class 中有一个 const 成员,编译器隐式删除了默认的复制构造函数。需要给它一个参数来初始化。

问题出在class

class Cube
{
private:
    std::array <Edgelet, 12> c_edgelets;
    //Other members...
public:
    //The constructor
    Cube(int size)
    
    //Other public members...

此 class 包含先前 class 对象的 std::array。我如何初始化这个数组? size参数需要给std::array的每个元素进行初始化。我想将 std::array 的每个元素设置为 Edgelet(size - 2).

当然,我可以使用初始化列表,但是由于构造函数有 12 个元素和其他参数而不是所示,代码变得难看。此外,我用 6 个元素而不是 12 个元素进行了类似的处理。

我也尝试为参数提供默认值,但由于有一个 const 成员,该值以后无法更改。我也试过研究 std::initializer_list 但似乎你不能向它添加新元素(或者你可以??)。有没有有效的方法来做到这一点?

如果数组成员不可默认构造,则必须为每个元素提供一个初始化程序。您可以使用 std::vector 而不是 std::array,而不是这样做。 std::vector 有一个

形式的构造函数
constexpr vector( size_type count,
                  const T& value,
                  const Allocator& alloc = Allocator());
                  

这将构造 count 个用 value 初始化的对象。这将使您的代码看起来像

class Cube
{
private:
    std::vector<Edgelet> c_edgelets;
    //Other members...
public:
    //The constructor
    Cube(int size) : c_edgelets(12, Edgelet(size - 2)) {}
    
    //Other public members...
};

你可以写 helper class:

template <std::size_t ... Is, typename T>
std::array<T, sizeof...(Is)> make_array_impl(const T& def, std::index_sequence<Is...>)
{
    return {{(Is, void(), def)...}};
}

template <std::size_t N, typename T>
std::array<T, N> make_array(const T& def)
{
    return make_array_impl(def, std::make_index_sequence<N>());
}

然后

Cube(int size) : c_edgelets(make_array<12>(Edgelet(size - 2)) {}