如何为该结构实现 [] 运算符?

发布于 2024-10-03 23:54:28 字数 412 浏览 6 评论 0原文

我想要像下面这样的东西:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

有深☉意 2024-10-10 23:54:28

您的订阅运算符应该返回一个代理对象,该对象本身会实现订阅运算符。

如果我们分解对 obj[2][3] = 6 的调用,这将产生:

  • obj[2] -->代理对象
  • 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 object
  • obj[2][6] --> reference to int

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.

徒留西风 2024-10-10 23:54:28

你可以这样做(尽管每个维度都有新模板)。

template <class T, size_t m, size_t n>
struct Container{
 public:
  int& operator()(size_t i, size_t j)
  {
      return containment[i][j];
  }

 private:
  T containment[m][n];
};

Container<int, 3, 4> ints;
ints(0,3) = 5;

或者您可以使用 Boost.MultiArray,并且省去很多痛苦。

Boost MultiArray 库增强了
C++ 标准容器
多功能多维数组
抽象。它包括一个通用的
数组类模板和本机数组
支持惯用数组的适配器
操作并与 C++ 互操作
标准库容器和
算法。这些数组共享一个共同的
接口,表示为通用的
根据泛型进行编程
可以实现数组算法。

You could do it something like this (new template for each dimensionality though).

template <class T, size_t m, size_t n>
struct Container{
 public:
  int& operator()(size_t i, size_t j)
  {
      return containment[i][j];
  }

 private:
  T containment[m][n];
};

Container<int, 3, 4> ints;
ints(0,3) = 5;

Or you could use Boost.MultiArray, and save a lot of pain.

The Boost MultiArray library enhances
the C++ standard containers with
versatile multi-dimensional array
abstractions. It includes a general
array class template and native array
adaptors that support idiomatic array
operations and interoperate with C++
Standard Library containers and
algorithms. The arrays share a common
interface, expressed as a generic
programming in terms of which generic
array algorithms can be implemented.

破晓 2024-10-10 23:54:28

困难在于知道operator[]的返回类型。您可以尝试这样的事情:

template <class T, size_t N>
struct Container {
T containment[N];
T &operator[](size_t index) { return containment[index]; }
};

Container<int[2][6], 5> obj;

或者您可以根据自身定义容器:

Container<Container<Container<int[6]>[2]>[5]> obj;

The difficulty is in know the return type of operator[]. You could try something like this:

template <class T, size_t N>
struct Container {
T containment[N];
T &operator[](size_t index) { return containment[index]; }
};

Container<int[2][6], 5> obj;

Alternatively you could define Container in terms of itself:

Container<Container<Container<int[6]>[2]>[5]> obj;
醉南桥 2024-10-10 23:54:28

谁想到参考会在这里发挥作用?我!
感谢 Niki Yoshiuchi,我想要的确切框架答案如下:

template <class T, size_t N>
struct Container {
private:
 T containment[N];
public:
 T & operator[](size_t index) { return containment[index]; }
};

Container<int[3][3][3],2> obj;
obj[1][1][1][1]=7;

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:

template <class T, size_t N>
struct Container {
private:
 T containment[N];
public:
 T & operator[](size_t index) { return containment[index]; }
};

Container<int[3][3][3],2> obj;
obj[1][1][1][1]=7;
西瑶 2024-10-10 23:54:28

制作 n 维集合的基础知识是这样的。它假定容器无法重新调整尺寸。

template< typename T >
class MultiDimContainer
{
   std::vector<size_t> dims;

   std::vector<T> data;

public:
   MultiDimContainer( const std::vector<size_t> dims )
   {
       // work out the product of dims and set data to that size
   }

   T& at( const std::vector<size_t> & dim )
   {
      // calculate where it lives in memory and return that element
   }
};

由于我已经实现了 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.

template< typename T >
class MultiDimContainer
{
   std::vector<size_t> dims;

   std::vector<T> data;

public:
   MultiDimContainer( const std::vector<size_t> dims )
   {
       // work out the product of dims and set data to that size
   }

   T& at( const std::vector<size_t> & dim )
   {
      // calculate where it lives in memory and return that element
   }
};

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文