C++ Can';从std::array私下继承时,从std::initializer\u列表构造t

C++ Can';从std::array私下继承时,从std::initializer\u列表构造t,c++,inheritance,stl,containers,private,C++,Inheritance,Stl,Containers,Private,我正试图制作一个std::array的包装器,以按照的建议执行边界检查。这是我的代码: template <typename T, size_t N> class Array : private std::array<T, N> { public: using std::array<T, N>::array; T operator[](size_t i) { return this->at(i); }

我正试图制作一个std::array的包装器,以按照的建议执行边界检查。这是我的代码:

template <typename T, size_t N>
class Array : private std::array<T, N> {
public:
    using std::array<T, N>::array;

    T operator[](size_t i) {
        return this->at(i);
    }

    T operator[](size_t i) const {
        return this->at(i);
    }
};

int main() {
    Array<int, 3> arr = {0,0,0};
}

模板
类数组:私有std::数组{
公众:
使用std::array::array;
T运算符[](大小\u T i){
返回此->在(i);
}
T运算符[](大小)常数{
返回此->在(i);
}
};
int main(){
数组arr={0,0,0};
}
当我尝试运行它时,我得到以下错误:
错误:没有匹配的构造函数用于初始化“Array”

如果我使用std::array::array省略了
并将其公开继承代码可以工作,但不建议使用此选项

我错过了什么?为什么我的类不能创建这样的实例


提前谢谢

std::array
结构未实现采用
初始值设定项列表的构造函数。它实际上只有一个隐式定义的构造函数<但是,代码>标准::数组
,per确实满足聚合的条件,因此它可以通过
{1,2,3}
进行初始化

规定的骨料要求(来自)

没有虚拟基类、专用基类或受保护基类

因此,您的类将不能与
私有
基类一起工作

请注意,即使将基类
公开
,最终也会违反
[dcl.init.aggr]/1.1
,其中

没有用户提供、显式或继承的构造函数

因此,您必须使用语句摆脱


有关工作示例,请参见。

std::array
结构未实现采用
初始值设定项列表的构造函数。它实际上只有一个隐式定义的构造函数<但是,代码>标准::数组
,per确实满足聚合的条件,因此它可以通过
{1,2,3}
进行初始化

规定的骨料要求(来自)

没有虚拟基类、专用基类或受保护基类

因此,您的类将不能与
私有
基类一起工作

请注意,即使将基类
公开
,最终也会违反
[dcl.init.aggr]/1.1
,其中

没有用户提供、显式或继承的构造函数

因此,您必须使用语句摆脱


有关工作示例,请参阅。

std::array
设计为聚合。它没有用户提供的构造函数,因此可以使用聚合初始化对其进行初始化。因为
数组
类有一个私有基类,所以它不是聚合,只能由构造函数初始化

另一种看待它的方式是,由于
Array
具有对用户隐藏的成员,因此该语言不允许用户使用聚合语法直接初始化这些元素,就像初始化普通数组一样。相反,用户必须调用构造函数,其中
数组
类的作者已显式地实现了必要的初始化逻辑,以实现
数组
类的契约

一个简单的解决方案是将
std::array
基类公开。如果您不想这样做,您可以编写自己的
初始值设定项\u list
构造函数,但这很棘手,也不完美:

// delegate to a helper constructor
Array(std::initializer_list<T> il) : Array(il, std::make_index_sequence<N>{}) {}

private:
template <size_t... i>
Array(std::initializer_list<T> il, std::index_sequence<i...>)
  : std::array<T, N>{(i < il.size() ? il.begin()[i] : T{})...} {}
//委托给助手构造函数
数组(std::initializer_list il):数组(il,std::make_index_sequence{})
私人:
模板
数组(std::初始值设定项\列表il,std::索引\序列)
:std::数组{(i
助手构造函数使用初始值设定项列表中的元素来初始化相应的
std::array
元素(如果存在);否则,它将从
T{}
初始化它


这方面的主要问题是,如果
T
是一个无法进行值初始化的类,那么即使提供了
N
初始值设定项,也无法调用该
Array
构造函数,因为编译器无法在编译时强制执行“
il
包含
N
元素”条件,因此必须假设可以在运行时调用
T{}
。没有办法完美地模拟聚合初始化。

std::array
被设计为聚合。它没有用户提供的构造函数,因此可以使用聚合初始化对其进行初始化。因为
数组
类有一个私有基类,所以它不是聚合,只能由构造函数初始化

另一种看待它的方式是,由于
Array
具有对用户隐藏的成员,因此该语言不允许用户使用聚合语法直接初始化这些元素,就像初始化普通数组一样。相反,用户必须调用构造函数,其中
数组
类的作者已显式地实现了必要的初始化逻辑,以实现
数组
类的契约

一个简单的解决方案是将
std::array
基类公开。如果您不想这样做,您可以编写自己的
初始值设定项\u list
构造函数,但这很棘手,也不完美:

// delegate to a helper constructor
Array(std::initializer_list<T> il) : Array(il, std::make_index_sequence<N>{}) {}

private:
template <size_t... i>
Array(std::initializer_list<T> il, std::index_sequence<i...>)
  : std::array<T, N>{(i < il.size() ? il.begin()[i] : T{})...} {}
//委托给助手构造函数
数组(std::initializer_list il):数组(il,std::make_index_sequence{})
私人:
模板
数组(std::初始值设定项\列表il,std::索引\序列)
:std::数组{(i
助手构造函数使用初始值设定项列表中的元素来初始化相应的
std::array
元素(如果存在);否则,它将从
T{}
初始化它

这方面的主要问题是,如果
T
是一个不能进行值初始化的类,那么这个
Array
构造