2017-08-23 73 views
1

我試圖用C++模板模板參數工作,與著名的堆棧例子:C++模板的模板:不能訪問私有成員

不過,我在下面的代碼得到acompilation錯誤。我的理解是,​​和'Stack<T, CONT>'是相同的類,所以'容器'在'Stack<T, CONT>::operator = (const Stack<T2, CONT2>& rhs)'

可以幫助我嗎?在使用模板模板參數時,有什麼特別的地方需要注意嗎?

template <typename T, 
    template < typename ELEM, typename ALLOC = std::allocator<ELEM> > class CONT = std::deque > 
class Stack 
{ 
    CONT<T> container ; 

public : 
    Stack() {} ; 
    template <typename T2> 
    void push_back (const T2& elem) ; 
    bool isEmpty (void) const ; 

    template <typename T2, 
     template < typename ELEM2, typename = std::allocator<ELEM2> > class CONT2 > 
     Stack<T, CONT>& operator = (const Stack<T2,CONT2>& rhs) ; 

    void push_back (T const& elem) { 
     container.push_back (elem) ; 
    }; 
    T operator [] (size_t i) const ; 
    T& operator [] (size_t i) ; 
}; 

template <typename T, template <typename ELEM, typename ALLOC > class CONT > 
T Stack<T, CONT>::operator [] (size_t i) const { 
    return container [i] ; 
} 

template <typename T, template <typename ELEM, typename ALLOC > class CONT > 
T& Stack<T, CONT>::operator[] (size_t i) 
{ 
    return container [i] ; 
} 

template <typename T, template <typename ELEM, typename ALLOC > class CONT > 
template <typename T2, template < typename , typename > class CONT2 > 
    Stack<T, CONT>& Stack<T, CONT>::operator = (const Stack<T2, CONT2>& rhs) 
{ 
    if (this->container != rhs.container) // ERROR !!! 
    { 
     if (this->container.size() == 0) 
     { 
      for (size_t i = 0 ; i < rhs.container.size() ; ++i) 
      { 
       (*this).container.push_back((T) rhs[i]) ; 
      } 
     } 
     else 
     { 
      for (size_t i = 0 ; i < this->container.size() ; ++i) 
      { 
       (*this)[i] = rhs[i] ; 
      } 
     } 
    } 

    return *this ; 
} 

int main() 
{ 
    Stack<int> stk ; 
    Stack<double> stkd ; 

    stk.push_back(10) ; 
    stk.push_back(5) ; 

    stkd = stk ; 

    int st = stk[1] ; 

    return 0; 

} 

的編譯錯誤是:

>e:\project2\project2\source.cpp(46): error C2248: 'Stack<T>::container' : cannot access private member declared in class 'Stack<T>' 
1>   with 
1>   [ 
1>    T=int 
1>   ] 
1>   e:\project2\project2\source.cpp(12) : see declaration of 'Stack<T>::container' 
1>   with 
1>   [ 
1>    T=int 
1>   ] 
1>   e:\project2\project2\source.cpp(75) : see reference to function template instantiation 'Stack<T> &Stack<T>::operator =<int,std::deque>(const Stack<int> &)' being compiled 
1>   with 
1>   [ 
1>    T=double 
1>   ] 
1>   e:\project2\project2\source.cpp(75) : see reference to function template instantiation 'Stack<T> &Stack<T>::operator =<int,std::deque>(const Stack<int> &)' being compiled 
1>   with 
1>   [ 
1>    T=double 
1>   ] 
+4

不,'棧'和'堆棧'ARA不同的類。 – songyuanyao

+1

堆棧不是一個開始的類。這是一個類模板。 –

+0

加上:模板朋友類堆棧;' – user5821508

回答

2

模板是編譯器用來構建實際的類的藍圖。因此,無論何時使用具有特定參數的模板類,編譯器都會根據提供的藍圖創建一個類。

讓我們來看看這個(極簡化的)例子:

template < typename T > 
class Test { 
    T member: 
}; 

現在,當您創建一個Test<int>Test<double>編譯器會生成兩個類這樣的:

class Test/* some information comes here, so that the compiler can differentiate different Test classes */ 
{ 
    int member; 
}; 

class Test/* again some additional information */ 
{ 
    double member; 
}; 

雖然他們看起來相當相似,它們並不相同。同樣的事情適用於你的Stackstkdstk有不同的類型,因此不能分配給另一個。


爲了解決這個問題,你可以讓每一個編譯器生成的模板實例彼此的朋友,像這樣:

template <typename T, 
    template < typename ELEM, typename ALLOC = std::allocator<ELEM> > class CONT = std::deque > 
class Stack { 
    /* ... */ 

public : 

    /* ... */ 

    template<class Other, 
     template < typename elem, typename allod = std::allocator<elem> > class cont > 
     friend class Stack; 

    /* ... */ }; 

請注意,這不會讓你到不同的容器進行比較,讓你需要找到另一種防止自我分配的方法(如果有人在這裏有一個好主意,隨時可以添加它)。下面是修改的賦值操作符:

template <typename T, template <typename ELEM, typename ALLOC > class CONT > 
template <typename T2, template < typename , typename > class CONT2 > 
    Stack<T, CONT>& Stack<T, CONT>::operator = (const Stack<T2, CONT2>& rhs) 
{ 

    /* self assignment check needed */ 
    { 
     if (this->container.size() == 0) 
     { 
      for (size_t i = 0 ; i < rhs.container.size() ; ++i) 
      { 
       (*this).container.push_back((T) rhs[i]) ; 
      } 
     } 
     else 
     { 
      for (size_t i = 0 ; i < this->container.size() ; ++i) 
      { 
       (*this)[i] = rhs[i] ; 
      } 
     } 
    } 

    return *this ; 
} 
+0

如何解決這將是很好 – sp2danny

+0

@ sp2danny在這裏你是。 – muXXmit2X

+0

嗯,我沒有看到這個自我分配的東西是關於什麼的? T1 = T2將由默認賦值運算符處理,而不是由模板重載處理,並且不將T1!= T2限定爲獨立於T1和T2內容的自賦值是合理的,是不是? – DrSvanHay