我正在尝试使用C ++中的模板模板参数,使用着名的Stack示例:
但是我在下面的代码中遇到了编译错误。我的理解是'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:\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> ]
答案 0 :(得分: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;
};
虽然看起来非常相似,但它们并不相同。同样的事情适用于您的Stack
。 stkd
和stk
具有不同的类型,因此无法彼此分配。
要解决此问题,您可以使每个编译器生成的模板实例成为彼此的朋友,如下所示:
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 ;
}