2010-11-22 87 views
3

我想是这样的下面:如何为这个结构实现[]运算符?

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... 

但经过几次尝试后,我发现自己卡住了,怎么可能?

+0

顺便说一句,你为什么需要这样的容器?考虑boost :: array或boost :: multi_array怎么样? – upriser 2010-11-22 17:27:07

回答

1

谁想参考会在这里发挥作用?我!
由于尼基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; 
5

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

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

  • obj[2] - >代理对象
  • obj[2][6] - >参考int

通过查看obj1你会意识到除了最后的[]之外的所有应该返回一个代理对象。

这通常是通过使用带有“深度”参数的模板化代理,并将其专用于合适的深度。在你的情况下,你的代理将有一个指向T的指针,它可能产生的第一个元素,以及维度列表(作为模板参数)。

虽然它并不是微不足道的,因为你希望看到任意数量的参数。取决于你的目标编译器是否支持可变参数模板,你确实可能会遇到一些麻烦。

+0

检查我自己的答案。 – Pooria 2010-11-22 17:57:23

3

你可以这样做(每个维度的新模板)。

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,并节省很多痛苦。

升压的MultiArray库增强 C++标准集装箱与 多功能多维数组 抽象。它包括一个支持惯用数组 操作和与C++ 标准库容器和 算法互操作的通用 阵列类模板和本地阵列 适配器。这些阵列共享一个通用的接口,表示为通用的 编程,根据该编程可以实现通用的 阵列算法。

+0

这个设计的一个问题是每个模板都应该有一个新的名字,因为你不能专注于不同的arity。一个常见的解决方案是具有虚拟参数(使用默认值)。关于Boost.MultiArray的好消息,除了锻炼一个自我之外,最好重用现有的解决方案:) – 2010-11-22 17:38:39

+0

@Matthieu - 是的,这也不允许`operator [] []`notation没有更多的工作。我可能可以忍受`Array2D`,`Array3D`等痛苦。我怎么能忍受不使用`Boost.MultiArray`的痛苦,知道它在那里? – 2010-11-22 17:43:45

+0

正如我在我以前说过的,除非编写一个练习,没有重新发明轮子,这是我upvoted这个答案:) – 2010-11-22 17:52:46

2

难度在于知道返回类型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; 
0

使得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 
    } 
}; 

正如我已经在()采用一个参数,你可以使用operator []来实现这个。你可能会想要2重载,一个const和一个非const,并且at()会检查边界,而operator []不会。您可能需要一个帮助器(非模板)函数来计算数据向量中此元素的位置。

当然,构建矢量是一个多步骤的过程,所以你可以使用一些魔法类来构造一个。

您也可以让operator []为您的容器取一个size_t并返回一个ContainerReferencer对象。这不是一个真正的多维数组,而是其他地方的数据片。再次可以有const或非const版本。

使用此模型不可能获取operator []的多个调用以过滤到T value_type或对其引用。

这将有可能使用一个硬尺寸的数组,这可能是一个模板参数。所以,如果你知道它是4维,你会称它为

MultiDimCollection <双,4>

,它总是有4个维度。然后你可以让运算符[]返回一个MultiDimCollectionReference < double,3>

这将会下降到2和1(一个向量),那么这将专门返回一个标量。