从 std::数组私下继承时无法从 std::initializer_list 构造
Can't construct from std::initializer_list when privately inheriting from std::array
我正在尝试制作 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};
}
当我尝试运行它时,出现以下错误:error: no matching constructor for initialization of 'Array<int, 3>'
。
如果我省略using std::array<T, N>::array;
行并公开继承它,代码就可以工作,尽管此选项是不可取的。
我在这里错过了什么?为什么我的类不能创建这样的实例?
提前感谢!
std::array
结构体不实现采用initializer_list
的构造函数。它实际上只有一个隐式定义的构造函数。std::array
,根据[array.cons]
,确实满足聚合的条件,所以它可以通过{1,2,3}
进行初始化。
指定的聚合要求(从[dcl.init.aggr]/1.4
开始(
没有虚拟、私有或受保护的基类
因此,您的类将无法与private
基类一起使用。
请注意,即使你把基类public
,你最终也会违反[dcl.init.aggr]/1.1
,它指出
没有用户提供的、显式的或继承的构造函数
所以你必须摆脱你的using
陈述。
有关工作示例,请参阅此处。
std::array
被设计为一个聚合。它没有用户提供的构造函数,因此可以使用聚合初始化对其进行初始化。由于Array
类具有私有基类,因此它不是聚合,只能由构造函数初始化。
另一种看待它的方法是,由于Array
具有对用户隐藏的成员,因此该语言允许用户使用聚合语法直接初始化这些元素是没有意义的,就像初始化普通数组一样。相反,用户必须调用构造函数,其中Array
类的作者已显式实现必要的初始化逻辑以履行Array
类的协定。
一个简单的解决方案是将std::array
基类公开。如果你不想这样做,你可以编写自己的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{})...} {}
帮助程序构造函数使用初始值设定项列表中的元素来初始化相应的std::array
元素(如果存在(;否则,它将从T{}
初始化它。
这样做的主要问题是,如果T
是一个无法进行值初始化的类,那么即使提供了N
初始值设定项,也无法调用此Array
构造函数,因为编译器无法在编译时强制执行"il
包含N
元素"条件,因此必须假定T{}
可以在运行时调用。没有办法完美地模拟聚合初始化。
- 使用std::multimap迭代器创建std::list
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 如何导出包含具有"std::unique_ptr"值的"std::map"属性的
- 从持续时间构造std::chrono::system_clock::time_point
- std::具有相同基类的类的变体
- std::向量与传递值的动态数组
- 使用 std::min "no matching function for call to ‘min(<brace-enclosed initializer list>)’"时出错
- std::move in initializer lists
- "默认参数":无法从'initializer list'转换为'std::initializer_list'
- 无法运行简单的 std::async 和 std::future 测试程序。错误:"has initializer but incomplete type."发生了什么?
- 在GCC中使用Brace Initializer初始化成员STD ::数组时错误
- VS2015无法从'initializer list'转换为'std::string'错误
- 如何使用 std::array 的默认参数? "array must be initialized with a brace-enclosed initializer"
- 为什么我会收到"variable 'std::packaged_task<int> task' has initializer but incomplete type"错误
- 为什么从std::string的initializer列表中填充std::向量不会调用std::字符串构造函数
- 如何解决"Variable 'std::ifstream myfile' has initializer but incomplete type"
- 将Initializer Lists与std::map一起使用
- <function-style-cast> 错误:无法从'initializer list'转换为'std::thread'