如何在类模板的成员初始值设定项列表中初始化数组类型的数据成员?

lei*_* hu 1 c++ arrays member-initialization c++14 index-sequence

例如,我有一个名为 的类Vector表示向量,还有一个名为 的类Integer表示整数。

class Integer{
public:
   Integer(int v):value_(v){};
private:
   int value_;
};
template<uint32_t Dim>
class Vector{
public:
     Vector(int v[Dim]) 
      ://How to initialize each element of the value_ array here?
     {
     }
private:
     Integer value_[Dim];
}
Run Code Online (Sandbox Code Playgroud)

由于Integer没有默认构造函数,因此必须value_在 的成员初始值设定项列表中初始化数组的每个元素Vector。但是,由于数组的长度是模板参数,因此不能直接使用类似value_{v[0], v[1], v[2]}value_ 数组的东西来初始化。我正在使用c++14。

Jan*_*tke 5

正如你所说,如果知道大小,你可以value_{v[0], v[1], v[2]}直接写。

解决方案A-std::index_sequence

鉴于大小未知,您可以编写如下内容:

private:
template <std::size_t... I>
Vector(const int(&v)[N], std::index_sequence<I...>)
  : value_{v[I]...} {}

public:
Vector(const int(&v)[Dims])
  : Vector(v, std::make_index_sequence<Dims>{}) {}
Run Code Online (Sandbox Code Playgroud)

注意:这使用对数组的引用,以便检查大小。

包扩展的v[I]...作用类似于v[0], v[1], ...任意数量Dims的索引(如使用 . 创建索引序列时指定的那样)std::make_index_sequence。

解决方案 B -聚合初始化

但是,由于您的Vector类仅包含一个数组成员,因此没有构造函数并依赖聚合初始化会更容易。如果你没有构造函数,你Vector<3>{1, 2, 3}也可以这样写。

解决方案C——std::array

您还可以有一个构造函数:

// note: value_ should be std::array as well
Vector(const std::array<int, Dims>& content) : value_{content} {}
Run Code Online (Sandbox Code Playgroud)

std::array具有值语义,并且使问题变得微不足道,因为您可以像任何其他对象一样复制/移动它。

进一步的解决方案

请参阅从固定大小的 std::span 创建固定大小的 std::array 的惯用方法是什么?。这个问题是关于C++20的,但是那里的解决方案也适用于旧版本。