想要将一个const_iterator转换成iterator供相关函数调用,直观的做法是使用const_cast,如下所示:
typedef std::deque<int> IntDeque;
typedef IntDeque::iterator Iter;
typedef IntDeque::const_iterator ConstIter;
constIter ci;
...
Iter i(ci); // 编译失败,从const_iterator到iterator没有隐式转换途径
Iter i(const_cast<Iter>(ci)); // 依然时编译错误,不能将const_iterator强制转换成iterator
包含显示类型转换的代码不能通过编译的原因在于:
对于这些容器类型,iterator和const_iterator是完全不同的类,它们之间的关系甚至比string和complex<double>之间的关系还要远。试图将一种类型转换为另一种类型是毫无意义的,这就是const_static转换被拒绝的元素。
不过,对于vector和string容器而言,以上包含const_cast的代码也许可能通过编译。不过即使对于它们,将const迭代器强制转换成迭代器也是不可取的,因为这些代码的移植性将是一个问题。
下面是安全的、可移植的途径:
typedef std::deque<int> IntDeque;
typedef IntDeque::iterator Iter;
typedef IntDeque::const_iterator ConstIter;
IntDeque d;
ConstIter ci;
...
Iter i(d.begin());
advance(i, distance(i, ci));
这段代码依然会编译失败,原因是distance无法推导出迭代器类型。
distance的函数声明为:
template<typename InputIterator>
typename iterator_traits<InputIterator>::difference_type distance(InputIterator first, InputIterator last);
需要根据distance的两个参数推导出InputIterator的类型,而i的类型为IntDeque::iterator,ci的类型为IntDeque::const_iterator,
两种不同的类型无法推导出一种类型,编译失败。
要想要distance顺利通过编译,需要排序二义性。
通过指明distance所使用的类型参数,从而避免让编译器来推断该类型参数。
最终的版本为:
typedef std::deque<int> IntDeque;
typedef IntDeque::iterator Iter;
typedef IntDeque::const_iterator ConstIter;
IntDeque d;
ConstIter ci;
...
Iter i(d.begin());
advance(i, distance<ConstIter>(i, ci));