如何为该结构实现 [] 运算符?
我想要像下面这样的东西:
template <class T>
struct Container{
public:
//[] operator
private:
T containment;
};
包含应该是一个具有任意选择性维数的数组,如下所示:
Container<int[20][4]> obj;
Container<int[5][2][6]> obj1;
//etc...
并且我想实现 [] 运算符,以便可以进行以下分配:
obj[2][3]=6;
obj1[1][1][3]=3;
//etc...
但经过几次尝试后,我发现自己卡住了,怎么可能?
I want to have something like this below:
template <class T>
struct Container{
public:
//[] operator
private:
T containment;
};
the containment is supposed to be an array with any selective number of dimensions as below:
Container<int[20][4]> obj;
Container<int[5][2][6]> obj1;
//etc...
And I want to implement the [] operator so that following assignments be possible:
obj[2][3]=6;
obj1[1][1][3]=3;
//etc...
But after a few tries I found myself stuck, how's that possible?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您的订阅运算符应该返回一个代理对象,该对象本身会实现订阅运算符。
如果我们分解对 obj[2][3] = 6 的调用,这将产生:
obj[2][6]
-->对int
的引用通过查看
obj1
,您将意识到除了最后一个[]
之外的所有内容都应该返回一个代理对象。这通常是通过使用带有“深度”参数的模板化代理来实现的,并将其专门化为合适的深度。在您的情况下,您的代理将有一个指向它可能生成的第一个元素的
T
指针,以及维度列表(作为模板参数)。但这并不是微不足道的,因为您似乎希望获得任意数量的参数。根据您的目标编译器是否支持可变参数模板,您可能确实会遇到一些麻烦。
Your subscription operator should return a proxy object, which would itself implement a subscription operator.
If we decompose the call to
obj[2][3] = 6
this would yield:obj[2]
--> proxy objectobj[2][6]
--> reference toint
By looking at
obj1
you'll realize that all but the last[]
should return a proxy object.This is typically down by using a templated proxy, with a "depth" parameter, and specialize it for the suitable depth. In your case, your proxy will have a pointer to
T
for the first element it might yield, as well as the list of dimensions (as template parameters).It isn't trivial though, because you wish for an arbitrary number of parameters it seems. Depending on whether or not your targetted compiler supports variadic templates you may be in for some grief indeed.
你可以这样做(尽管每个维度都有新模板)。
或者您可以使用 Boost.MultiArray,并且省去很多痛苦。
You could do it something like this (new template for each dimensionality though).
Or you could use Boost.MultiArray, and save a lot of pain.
困难在于知道
operator[]
的返回类型。您可以尝试这样的事情:或者您可以根据自身定义容器:
The difficulty is in know the return type of
operator[]
. You could try something like this:Alternatively you could define Container in terms of itself:
谁想到参考会在这里发挥作用?我!
感谢 Niki Yoshiuchi,我想要的确切框架答案如下:
Who thought reference would come into play here? me!
Thanks to Niki Yoshiuchi, The answer in exact framework that I want is as it follows:
制作 n 维集合的基础知识是这样的。它假定容器无法重新调整尺寸。
由于我已经实现了 at() 来获取单个参数,因此您可以使用运算符 [] 来实现此目的。您可能需要 2 个重载,一个 const 和一个非 const,并且 at() 会进行边界检查,而 operator[] 则不会。您可能需要一个辅助(非模板)函数来计算该元素在数据向量中的位置。
当然,构建向量是一个多步骤的过程,因此您可以使用一些魔术类来构建向量。
您还可以为您的容器使用operator[],它将采用单个size_t并返回一个ContainerReferencer对象。这不是真正的多维数组,而是其他地方保存的数据的切片。再次可能存在 const 或非 const 版本。
使用此模型不可能多次调用operator[]来过滤到T value_type或对其的引用。
可以使用硬维数组,它可以是模板参数。因此,如果您知道它是 4 维的,您可以将其称为
MultiDimCollection<双,4>
并且它总是有 4 个维度。然后你可以让operator[]返回一个MultiDimCollectionReference<双,3>
这将下降到 2 和 1(一个向量),然后将专门返回一个标量。
The basics of making an n-dimensional collection would be something like this. It assumes the container cannot be redimensioned.
As I have implemented at() to take a single parameter you can use operator[] for this. You would probably want 2 overloads, one const and one non-const, and at() would bounds check whilst operator[] would not. You would probably want one helper (non-template) function to calculate the location of this element in your data vector.
Of course, constructing the vector is a multi-step process so you could use some magic class to construct one.
You could also have operator[] for your container would take a single size_t and would return a ContainerReferencer object. This is not a real multi-dimensional array but a slice to data held elsewhere. Once again there could be const or non-const versions.
Getting multiple calls of operator[] to filter down to the T value_type or a reference to it is not possible using this model.
It would be possible using a hard-dimensioned array which could be a template parameter. So if you know it is 4-dimensions you would call it
MultiDimCollection< double, 4>
and it would always have 4 dimensions. You can then get operator[] to return a MultiDimCollectionReference< double, 3 >
this would go down to 2 and 1 (a vector) then that would be specialised to return a scalar.