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

时间:2017-08-23 07:22:45

标签: c++ templates

我正在尝试使用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>          ]

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

虽然看起来非常相似,但它们并不相同。同样的事情适用于您的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 ;
}