我强烈推荐马特·奥斯汀 (Matt Austern) 撰写的多布博士期刊 (Dr. Dobb's Journal) 的原创文章,题为“标准图书馆员:定义迭代器和常量迭代器” http://www.drdobbs.com/the-standard-librarian-defining-iterato/184401331,2001 年 1 月。如果该链接出现问题,现在 Dr. Dobb's 已经停止运营,它也可以使用here http://collaboration.cmc.ec.gc.ca/science/rpn/biblio/ddj/Website/articles/CUJ/2001/0101/austern/austern.htm.
为了防止这个替换答案被删除,我总结一下解决方案。
这个想法是将迭代器实现为一个带有额外模板参数的模板,该参数是一个布尔值,表示这是否是 const 版本。在实现中,const 和非 const 版本不同的任何地方,您都可以使用模板机制来选择正确的代码。马特·奥斯汀的机制被称为choose
。它看起来像这样:
template <bool flag, class IsTrue, class IsFalse>
struct choose;
template <class IsTrue, class IsFalse>
struct choose<true, IsTrue, IsFalse> {
typedef IsTrue type;
};
template <class IsTrue, class IsFalse>
struct choose<false, IsTrue, IsFalse> {
typedef IsFalse type;
};
如果您对 const 和非常量迭代器有单独的实现,那么 const 实现将包括如下所示的 typedef:
typedef const T &reference;
typedef const T *pointer;
并且非常量实现将具有:
typedef T &reference;
typedef T *pointer;
但与choose
,您可以有一个基于额外模板参数进行选择的实现:
typedef typename choose<is_const, const T &, T &>::type reference;
typedef typename choose<is_const, const T *, T *>::type pointer;
通过使用底层类型的 typedef,所有迭代器方法都可以具有相同的实现。参见马特·奥斯汀的完整的例子 http://collaboration.cmc.ec.gc.ca/science/rpn/biblio/ddj/Website/articles/CUJ/2001/0101/austern/list1.htm.