2011-08-01 45 views
2

這與稍後提出的問題略有不同。假設我有一個容器類,它有兩個模板參數,第一個是一個類型,第二個是容器的大小。包含類定義的模板容器只需要多個模板參數中的一個

現在我們有多個容器與不同的容器存儲大小。從本質上講,容器功能(無論如何都是公共的)實際上只關心T; N僅用於分配本地存儲(如果N不夠用,則使用分配器)。

我已經彙總了一個簡單的示例實現,展示了我遇到的問題。

#include <iostream> 

template <typename T, size_t N = 10> 
class TestArray 
{ 
public: 
    T Local[N]; 

    class Iterator 
    { 
    public: 
     T* Array; 
     int Index;  

     Iterator() : Array(NULL), Index(-1) { } 
     Iterator(T* _array, int _index) : Array(_array), Index(_index) { } 

     bool operator == (const Iterator& _other) const 
     { 
      return _other.Index == Index && _other.Array == Array; 
     } 

     bool operator != (const Iterator& _other) const 
     { 
      return !(*this == _other); 
     } 

     template <size_t _N> 
     Iterator& operator = (const typename TestArray<T, _N>::Iterator &_other) 
     { 
      Array = _other.Array; 
      Index = _other.Index; 

      return *this; 
     } 

     void Next() { ++Index; } 
     void Prev() { --Index; } 

     T& Get() { return Array[Index]; } 
    }; 

    T& operator [] (const int _index) { return Local[_index]; } 

    Iterator Begin() { return Iterator(Local, 0); } 
    Iterator End() { return Iterator(Local, N); } 

    template <size_t _N> 
    void Copy(const TestArray<T, _N> &_other, int _index, int _count) 
    { 
     int i; 

     for (i = 0; i < _count; i++) 
      Local[_index + i] = _other.Local[i]; 
    } 
}; 

這實際上是一個兩部分問題。我之前發佈的第一部分:Template container with multiple template parameters interacting with other template containers with a different template parameter。對於第二部分,我想如下使用它:

int main() { 

    TestArray<int> testArray1; 
    TestArray<int, 25> testArray2; 

    TestArray<int>::Iterator itr; 

    itr = testArray1.Begin(); 

    for (itr = testArray1.Begin(); itr != testArray1.End(); itr.Next()) 
    { 
     itr.Get() = itr1.Index; 
    } 

    testArray2.Copy(testArray1, 0, 10); 

    for (itr = testArray2.Begin(); itr != testArray2.End(); itr.Next()) 
    { 
     std::cout << itr.Get() << std::endl; 
    } 

    return 0; 
} 

這裏是一個IDEONE鏈接:

http://ideone.com/GlN54

當用gcc-4.3.4,我得到以下編譯

prog.cpp: In function ‘int main()’: 
prog.cpp:67: error: no match for ‘operator=’ in ‘itr = testArray2.TestArray<T, N>::Begin [with T = int, unsigned int N = 25u]()’ 
prog.cpp:10: note: candidates are: TestArray<int, 10u>::Iterator& TestArray<int, 10u>::Iterator::operator=(const TestArray<int, 10u>::Iterator&) 
prog.cpp:67: error: no match for ‘operator!=’ in ‘itr != testArray2.TestArray<T, N>::End [with T = int, unsigned int N = 25u]()’ 
prog.cpp:19: note: candidates are: bool TestArray<T, N>::Iterator::operator!=(const TestArray<T, N>::Iterator&) const [with T = int, unsigned int N = 10u] 

在VS2010,我得到如下:

1>------ Build started: Project: testunholytemplatemess, Configuration: Debug Win32 ------ 
1> main.cpp 
1>c:\users\james\documents\testproj\testunholytemplatemess\testunholytemplatemess\main.cpp(67): error C2679: binary '=' : no operator found which takes a right-hand operand of type 'TestArray<T,N>::Iterator' (or there is no acceptable conversion) 
1>   with 
1>   [ 
1>    T=int, 
1>    N=25 
1>   ] 
1>   c:\users\james\documents\testproj\testunholytemplatemess\testunholytemplatemess\main.cpp(34): could be 'TestArray<T>::Iterator &TestArray<T>::Iterator::operator =(const TestArray<T>::Iterator &)' 
1>   with 
1>   [ 
1>    T=int 
1>   ] 
1>   while trying to match the argument list '(TestArray<T>::Iterator, TestArray<T,N>::Iterator)' 
1>   with 
1>   [ 
1>    T=int 
1>   ] 
1>c:\users\james\documents\testproj\testunholytemplatemess\testunholytemplatemess\main.cpp(67): error C2679: binary '!=' : no operator found which takes a right-hand operand of type 'TestArray<T,N>::Iterator' (or there is no acceptable conversion) 
1>   with 
1>   [ 
1>    T=int, 
1>    N=25 
1>   ] 
1>   c:\users\james\documents\testproj\testunholytemplatemess\testunholytemplatemess\main.cpp(19): could be 'bool TestArray<T>::Iterator::operator !=(const TestArray<T>::Iterator &) const' 
1>   with 
1>   [ 
1>    T=int 
1>   ] 
1>   while trying to match the argument list '(TestArray<T>::Iterator, TestArray<T,N>::Iterator)' 
1>   with 
1>   [ 
1>    T=int 
1>   ] 

我以爲Iterator& operator = WOU ld使它成爲這個賦值運算符應該工作,但顯然不是。也許我很厚,但我沒有在這裏確定正確的解決方案。有沒有人有什麼建議?

+0

你需要三巨頭!你有一個默認的構造函數和一個賦值重載,但是你沒有一個拷貝構造函數在你的迭代器上! –

+0

@Bob他使用默認的拷貝構造函數,不是嗎? –

+0

@VJo,只是指出三巨頭是重要的,它不是問題的答案。在這個例子中默認的拷貝構造函數是可以的,但遵循三巨頭法則總是很好的做法。 –

回答

6

TestArray<T, 1>TestArray<T, 2>不同類型等都是TestArray<T, 1>::IteratorTestArray<T, 2>::Iterator。作業不能工作! (您itr是從testArray2.Begin()類型不同的類型。)

整個建築看起來很可疑,我 - 這真的是必要的嗎?你想達到什麼目的?你看過std::array


更新:

for (itr.operator=<int,25>(testArray2.Begin()); 
     itr.operator!=<int,25>(testArray2.End()); 
     itr.Next()) 
    { 
    std::cout << itr.Get() << std::endl; 
    } 

我不完全知道爲什麼參數不能從參數被推斷,我期待着一個好:如果你提供的模板參數明確它的工作原理解釋 - 同時,我把完整代碼on Ideone,雖然它不在那裏編譯,但它與我的GCC 4.6.1。

+0

我假設重寫'operator ='將允許不同類型之間的分配。基礎類型仍然是'TestArray ',但它可以使用重寫的運算符進行分配。 – James

+0

這是一個IDEOne或這個答案:http://ideone.com/lnJE7 –

+0

那麼,錯誤消息肯定表明編譯器正在尋找相同的類型 - 你給我們正確的代碼? '!='運算符絕對不是模板! –

2

當您使用默認模板參數時,編譯器會自動提供默認值,但它們仍然是模板定義的一部分。在你的情況下,TestArray<int>TestArray<int, 10>相同。如果你希望它在TestArray<T, N> and TestArray<T, M>之間互相操作,你可能會想使用模板函數。

編輯:我已經能夠想出的唯一解決方案是將迭代器分解爲它自己的類,然後按需要工作。我無法告訴你的是爲什麼它不起作用。我的猜測是因爲它不喜歡搜索可能的模板擴展的內部類。無論哪種方式,這是我所做的。

#include <iostream> 

template <typename T, size_t N = 10> class TestArray; 

template<typename T, size_t N> 
    class TIterator 
    { 
    public: 
     T* Array; 
     int Index;  

     TIterator() : Array(NULL), Index(-1) { } 
     TIterator(T* _array, int _index) : Array(_array), Index(_index) { } 

     bool operator == (const TIterator& _other) const 
     { 
    return _other.Index == Index && _other.Array == Array; 
     } 

     bool operator != (const TIterator& _other) const 
     { 
    return !(*this == _other); 
     } 

     TIterator& operator = (const TIterator& _other) { 
    Array = _other.Array; 
    Index = _other.Index; 
    return *this; 
     } 

     template <size_t M> 
     bool operator == (const TIterator<T, M>& _other) const 
     { 
    return _other.Index == Index && _other.Array == Array; 
     } 

     template <size_t M> 
     bool operator != (const TIterator<T, M>& _other) const 
     { 
    return !(*this == _other); 
     } 

     template< size_t M> 
     TIterator& operator = (const TIterator<T, M>& _other) { 
    Array = _other.Array; 
    Index = _other.Index; 
     } 

     void Next() { ++Index; } 
     void Prev() { --Index; } 

     T& Get() { return Array[Index]; } 
    }; 



template <typename T, size_t N> 
class TestArray 
{ 
public: 
    T Local[N]; 

    typedef TIterator<T, N> Iterator; 

    T& operator [] (const int _index) { return Local[_index]; } 

    Iterator Begin() { return Iterator(Local, 0); } 
    Iterator End() { return Iterator(Local, N); } 

    template <size_t _N> 
    void Copy(const TestArray<T, _N> &_other, int _index, int _count) 
    { 
    int i; 

    for (i = 0; i < _count; i++) 
     Local[_index + i] = _other.Local[i]; 
    } 
}; 
int main() { 

    TestArray<int> testArray1; 
    TestArray<int, 25> testArray2; 
    TestArray<double, 10> testArray3; 

    TestArray<int>::Iterator itr; 

    itr = testArray1.Begin(); 

    for (itr = testArray1.Begin(); itr != testArray1.End(); itr.Next()) 
    { 
     itr.Get() = itr.Index; 
    } 

    testArray2.Copy(testArray1, 0, 10); 


    for (itr = testArray2.Begin(); itr != testArray2.End(); itr.Next()) 
    { 
     std::cout << itr.Get() << std::endl; 
    } 


    return 0; 
} 

注意,我有TIterator使用兩種類型的參數,即使它沒有技術上使用第二個模板參數,只是爲了顯示它的工作。

+0

正確的,這是我試圖用模板'operator ='來完成,但它似乎仍然不同意我的方法。 – James

+0

感謝您的更新。我想這是告訴我們這是一個合法的結構,但編譯器不會因爲它是一個內部類而玩球。 – James

相關問題