我可以继承std::array和重载运算符[]吗



这个问题很简单。我正在尝试定义一个自定义数组类,它具有普通std::数组的所有功能,但我想添加在代码库中定义的自定义类型中使用运算符[]的功能。一种选择是将我的类封装在std::数组中,类似于:

using MyType = double; // just an example
template<typename T, unsigned Size>
class MyArray
{
private:
std::array<T, Size> m_array{ 0 };
public:
T& operator [](MyType d) { return m_array[abs(round(d))]; }
void print()
{
for (int i : m_array) {
std::cout << i << std::endl;
}
}
};
int main()
{
MyType var = 0.5649;
MyArray<int, 5> vec;
vec[var] = 1;
vec.print();
return 0;
}

输出为

0 1 0 0 0 

正如预期的那样。这样做的缺点是,我无法访问典型的std::array接口的所有其余部分。所以我想为什么不让我的数组从std::array:继承呢

using MyType = double; // just an example
template<typename T, unsigned Size>
class MyArray : public std::array<T, Size>
{
public:
// Here I explicitely cast (*this) to std::array, so my operator [] is defined in terms
// of the std::array operator []
T& operator [](MyType var) { return std::array<T, Size>(*this)[abs(round(var))]; }
void print()
{
for (int i : (*this)) {
std::cout << i << std::endl;
}
}
};
int main()
{
MyType var = 2.123;
MyArray<int, 5> vec{ 0 };
vec[var] = 1;
vec.print();
return 0;
}

但在这种情况下,输出是

0 0 0 0 0

无论值或var如何,这意味着MyArray没有正常工作。我做错了什么?继承std::数组时,是否存在根本错误或不可能的情况?

继承本身是合法的,只要你不试图通过指向基类的指针来delete派生类,基类缺少虚拟析构函数。

问题是return std::array<T, Size>(*this)[abs(round(var))];创建了一个临时std::array,并返回对其元素的引用,该引用立即变为悬空,因为当函数返回时,临时会被破坏。

您希望return std::array<T, Size>::operator[](abs(round(var)));调用基类的operator[]。或者,您可以执行static_cast<std::array<T, Size> &>(*this)[abs(round(var))];


还要注意,如果嵌套了大括号,则大括号std::array的初始化是不稳定的。例如,std::array<std::pair<int, int>, 2> x = {{1,1},{1,1}};不起作用,需要一组额外的大括号:std::array<std::pair<int, int>, 2> x = {{{1,1},{1,1}}};

但是,如果添加继承,这也会停止工作,并且需要另一对大括号。

最新更新