nested dependent type names

一个《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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值