使用域作用限定符对类模版取出内嵌类型来typedef,编译器就会报错
template<class T>
class Nodeiterator{
};
template <class T>
class Tree{
public:
typedef Nodeiterator<T> iterator;
};
template <class T>
class map{
public:
typedef Tree<T>::iterator iterator;//这里会提示报错,让加上typename
};
解释下上面的原因,域作用限定符可以取,静态成员变量,还有内部类,嵌在里面的组合类,甚至还有函数,而这个时候,还没有实例化,不知道Tree这个iterator是究竟是什么。
看看下面的代码,依旧会报错,和上述原因类似,不妨分析下。
template <class T>
class Tree{
public:
typedef int iterator;
};
template <class T>
class map{
public:
typedef Tree<T>::iterator iterator;
};
const加类型其实算作单独一种类型
template<class T>
struct Node
{
Node<T>* tmp;
};
template<class T,class Ref,class Ptr>
class Nodeiterator{
public:
typedef Node<T>* node;
node p;
Nodeiterator(const node tp = node())
:p(p)
{
;
}
};
template <class T>
class Tree{
public:
Node<T>* root;
typedef Nodeiterator<const T,const T&,const T*> const_iterator;
const_iterator insert()
{
return const_iterator(root);//这里给搞错警告说没有合适的函数去调用
}
};
template <class T>
class set{
public:
Tree<T> m_tree;
typedef typename Tree<T>::const_iterator iterator;
void func()
{
iterator it = m_tree.insert();
}
};
经过半天的调试和分析:发现原来是因为,const T实际上对Node那里实例化了另外的节点了,也就是Node*的节点,导致类型不同,从而刀子没有合适的函数去调用,也就是没有针对
Node*的iterator了,这点是值得注意的。
相互依赖的类模板需要前置声明
// template <class T>
// class B;
template <class T>
class A{
friend B<T>;//这里就会报出编译错误
};
template <class T>
class B{
A<T> a;
};
上面这种情况,A种有B,B中有A成相互依赖,就导致一个问题。
粘贴上面代码,会发现,编译器报错说B不是一个类型名,原因就是编译器编译上而下,而这又是模板,两个确定又要看彼此,就会让编译器很为难,因此前置声明后面个模板类,如这里就是B。
把注释部分代码取消注释即可没有报错。