C++模板模板:无法访问私有成员

c++ template template : cannot access private member

本文关键字:成员 访问 C++      更新时间:2023-10-16

我正在尝试使用C++中的模板模板参数,著名的堆栈示例:

但是我在下面的代码中收到编译错误。我的理解是,'Stack<T2, CONT2>''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:project2project2source.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:project2project2source.cpp(12) : see declaration of 'Stack<T>::container'
1>          with
1>          [
1>              T=int
1>          ]
1>          e:project2project2source.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:project2project2source.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>          ]

模板是编译器用来构造实际类的蓝图。因此,每当使用具有特定参数的模板类时,编译器都会根据提供的蓝图创建一个类。

让我们看看这个(非常简化的(示例:

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

虽然它们看起来很相似,但它们并不相同。同样的事情也适用于您的Stack.stkdstk具有不同的类型,因此不能相互分配。


要解决此问题,您可以使模板的每个编译器生成的实例彼此成为朋友,如下所示:

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