2010-11-22 88 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(一個向量),那麼這將專門返回一個標量。