一个《Effective C++》中的例子,item 42
template<typename C> // print 2nd element in
void print2nd(const C& container) // container;
{ // this is not valid C++!
if (container.size() >= 2) {
C::const_iterator iter(container.begin()); // get iterator to 1st element
++iter; // move iter to 2nd element
int value = *iter; // copy that element to an int
std::cout << value; // print the int
}
}
这里的iter类型取决于模版参数C, 像iter这样的类型取决于模版参数的名字称为“dependent names”, C::const_iterator也是一个dependent name,而且它是一个类型,称为“dependent type names”。包含在某个类里的dependent name称为"nested dependent names"。
值得注意的是,"nested dependent names"默认不是类型("By default, nested dependent names are not types"[1]),所以上面这段代码编译通不过。给nested dependent names前面添加typename,告诉编译器其是个类型,即可编译通过了,如下:
template<typename C> // this is valid C++
void print2nd(const C& container)
{
if (container.size() >= 2) {
typename C::const_iterator iter(container.begin());
...
}
}
在《Thinking in C++》中第16章的TStack2.h中,也有nested dependent names:
//: C16:TStack2.h
// Templatized Stack with nested iterator
#ifndef TSTACK2_H
#define TSTACK2_H
template<class T> class Stack {
struct Link {
T* data;
Link* next;
Link(T* dat, Link* nxt)
: data(dat), next(nxt) {}
}* head;
public:
Stack() : head(0) {}
~Stack();
void push(T* dat) {
head = new Link(dat, head);
}
T* peek() const {
return head ? head->data : 0;
}
T* pop();
// Nested iterator class:
class iterator; // Declaration required
friend class iterator; // Make it a friend
class iterator { // Now define it
Stack::Link* p;
public:
iterator(const Stack<T>& tl) : p(tl.head) {}
// Copy-constructor:
iterator(const iterator& tl) : p(tl.p) {}
// The end sentinel iterator:
iterator() : p(0) {}
// operator++ returns boolean indicating end:
bool operator++() {
if(p->next)
p = p->next;
else p = 0; // Indicates end of list
return bool(p);
}
bool operator++(int) { return operator++(); }
T* current() const {
if(!p) return 0;
return p->data;
}
// Pointer dereference operator:
T* operator->() const {
require(p != 0,
"PStack::iterator::operator->returns 0");
return current();
}
T* operator*() const { return current(); }
// bool conversion for conditional test:
operator bool() const { return bool(p); }
// Comparison to test for end:
bool operator==(const iterator&) const {
return p == 0;
}
bool operator!=(const iterator&) const {
return p != 0;
}
};
iterator begin() const {
return iterator(*this);
}
iterator end() const { return iterator(); }
};
template<class T> Stack<T>::~Stack() {
while(head)
delete pop();
}
template<class T> T* Stack<T>::pop() {
if(head == 0) return 0;
T* result = head->data;
Link* oldHead = head;
head = head->next;
delete oldHead;
return result;
}
#endif // TSTACK2_H ///:~
其中,iterator类的成员变量Stack::Link* p就是nested dependent name,上面这段代码在VS2010中编译会报错。修改成
typename Stack::Link* p或struct Stack::Link* p即可编译通过。
参考:
[1]Scott Meyers. 《Effective C++ Third Edition 55 Specific Ways to Improve Your Programs and Designs》. Item42.
[2]Bruce Eckel. "Thinking in C++, 2nd ed, Vol 1". Chapter 16.