一个《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 } }
值得注意的是,"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 ///:~
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.