[英]Can't construct from std::initializer_list when privately inheriting from std::array
I'm trying to make a wrapper of std::array to perform boundary checks as suggested by this answer .我正在尝试制作 std::array 的包装器,以按照此答案的建议执行边界检查。 This is the code I have:
这是我的代码:
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};
}
When I try to run it I get the following error: error: no matching constructor for initialization of 'Array<int, 3>'
.当我尝试运行它时,出现以下错误:
error: no matching constructor for initialization of 'Array<int, 3>'
。
If I omit the line using std::array<T, N>::array;
如果我
using std::array<T, N>::array;
省略该行and inherit it publicly the code works, though this option is not advisable.并公开继承它的代码工作,虽然这个选项是不可取的。
What am I missing here?我在这里想念什么? Why can't my class create an instance like this?
为什么我的 class 不能创建这样的实例?
Thanks in advance!提前致谢!
The std::array
struct does not implement a constructor which takes an initializer_list
. std::array
结构没有实现采用initializer_list
的构造函数。 It actually only has an implicitly defined constructor.它实际上只有一个隐式定义的构造函数。
std::array
, per [array.cons]
, does meet the conditions for aggregate though, so it can be initialized via {1,2,3}
for example.每个
[array.cons]
的std::array
确实满足聚合的条件,因此可以通过例如{1,2,3}
对其进行初始化。
The requirements for aggregates specified (from [dcl.init.aggr]/1.4
)指定聚合的要求(来自
[dcl.init.aggr]/1.4
)
no virtual, private, or protected base classes
没有虚拟、私有或受保护的基类
Therefore, your class will not work with a private
base class.因此,您的 class 将无法与
private
基础 class 一起使用。
Note that even if you make the base class public
, you end up violating [dcl.init.aggr]/1.1
, which states请注意,即使您将基础 class 设为
public
,您最终也会违反[dcl.init.aggr]/1.1
,其中指出
no user-provided, explicit, or inherited constructors
没有用户提供的、显式的或继承的构造函数
So you would have to get rid of your using
statement.所以你必须摆脱你的
using
声明。
std::array
is designed to be an aggregate. std::array
被设计为一个聚合。 It has no user-provided constructors, so one can initialize it using aggregate initialization.它没有用户提供的构造函数,因此可以使用聚合初始化对其进行初始化。 Because your
Array
class has a private base class, it is not an aggregate, and can only be initialized by a constructor.因为您的
Array
class 有一个私有基 class,所以它不是聚合,只能由构造函数初始化。
Another way of looking at it is that since Array
has members that are hidden from the user, it does not make sense for the language to allow the user to directly initialize those elements using the aggregate syntax, the way one might initialize a normal array.另一种看待它的方式是,由于
Array
具有对用户隐藏的成员,因此语言允许用户使用聚合语法直接初始化这些元素是没有意义的,就像初始化普通数组的方式一样。 Instead the user must call a constructor, wherein the Array
class's author has explicitly implemented the necessary initialization logic to fulfill the Array
class's contract.相反,用户必须调用构造函数,其中
Array
类的作者已经明确实现了必要的初始化逻辑来履行Array
类的契约。
One simple solution is to make the std::array
base class public.一种简单的解决方案是将
std::array
基础 class 公开。 If you don't want to do that, you can write your own initializer_list
constructor, but it's tricky and imperfect:如果您不想这样做,您可以编写自己的
initializer_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{})...} {}
The helper constructor uses an element from the initializer list to initialize the corresponding std::array
element, if one exists;辅助构造函数使用初始值设定项列表中的一个元素来初始化相应的
std::array
元素(如果存在); otherwise, it initializes it from T{}
.否则,它从
T{}
初始化它。
The main problem with this is that if T
is a class that cannot be value-initialized, then this Array
constructor cannot be called even if N
initializers are supplied, because the compiler cannot enforce the " il
contains N
elements" condition at compile time, and thus must assume that T{}
may be called at runtime.这样做的主要问题是,如果
T
是无法进行值初始化的 class,那么即使提供了N
个初始化器,也无法调用此Array
构造函数,因为编译器无法在编译时强制执行“ il
contains N
elements”条件,因此必须假设T{}
可以在运行时调用。 There is no way to perfectly emulate aggregate initialization.没有办法完美地模拟聚合初始化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.