2

我正在尝试为向量算术编写一个容器类。对象的大小是静态的:

template<typename T, unsigned N>
class vec{
    T data[N] = {0};
public:
    vec(std::initializer_list<T> ini){
        std::copy(ini.begin(), ini.end(), data);
    }
}

这就是我走多远。

但是,我测试了 std::array 类进行比较,我注意到如果初始化列表太长或太短,它会以某种方式做出静态断言。

std::array<float, 2> a = {1, 2, 3, 4} <- instant error message from the visual studio ide

在我的课堂上,我必须在运行时检查初始化列表的长度。

我假设 std::array 类以某种方式管理它以使用初始化列表表示法直接初始化数据,而没有 std::initializer_list 类。

是否可以像 std::array 一样初始化我的类?

4

1 回答 1

2

std::array是一个聚合,因此它使用聚合初始化。在聚合初始化期间提供多余的元素是不正确的,需要进行诊断。编译器至少必须提供警告,gcc 和 clang 都会导致此错误。因此,如果您将您的类设为聚合,那么您可以让它以与 std::array 相同的方式工作。请注意,在类成员初始化程序中,您的类在 C++11 中是非聚合的,但在 C++14 中不是。

我们可以通过查看 C++11 标准草案23.3.2.1 [array.overview]看到它是一个聚合:

数组是可以使用语法初始化的聚合(8.5.1)

array<T, N> a = { initializer-list };

其中 initializer-list 是一个逗号分隔的列表,最多包含 N 个元素,其类型可转换为 T。

8.5.1 [dcl.init.aggr]部分涵盖聚合初始化并说:

如果初始化器子句的数量超过要初始化的成员或元素的数量,则初始化器列表是格式错误的。

标准草案提供了一种可能的实现方式,该实现方式缩短到最低限度,如下所示:

template <class T, size_t N>
struct array {
    T elems[N];
};

标准草案有一个注释,上面写着:

成员变量 elems 仅用于说明,以强调数组是类聚合。名称 elems 不是数组接口的一部分

这是一个聚合,如果提供了过多的元素,gcc 和 clang 都会提供错误。

另请参阅什么是聚合和 POD 以及它们如何/为什么特别?.

于 2015-09-15T01:53:42.430 回答