为什么std::distance不适用于const和nonconst迭代器的混合

Why std::distance doesnt work on mix of const and nonconst iterators?

本文关键字:nonconst 迭代器 混合 适用于 std distance 不适用 为什么 const      更新时间:2023-10-16

正如问题所说,我想知道原因。因为当我试图获取const和非const迭代器之间的距离时,我遇到了一个错误。

vector<int> v;
auto it=v.begin();
auto cit=v.cbegin();
distance(it,cit);

no matching function for call to ‘distance(__gnu_cxx::__normal_iterator<int*, std::vector<int> >&, __gnu_cxx::__normal_iterator<const int*, std::vector<int> >&)

从我对迭代器的有限理解来看,我看不出它为什么不工作。

在对std::distance的调用中有一个可变迭代器和一个常量迭代器,因此模板参数推导失败。可以通过显式指定模板参数来解决此问题。

std::vector<int> v;
auto i1 = v.begin();
auto i2 = v.cbegin();
auto dist = std::distance<std::vector<int>::const_iterator>( i1, i2 );

这是因为std::distance()只接受一个模板参数:

template <class InputIterator>
iterator_traits<InputIterator>::difference_type
distance(InputIterator first, InputIterator last);

因此,firstlast必须可转换为同一类型,不幸的是,模板解析不会考虑vector<int>::iterator可转换为vector<int>::const_iterator

正如大家所说,这是因为std::distance只采用一种迭代器类型,而模板参数推导无法选择它应该是哪一种(即使只有一种可能,因为iterator转换为const_iterator,但不能转换回来)。

可能值得写一个类似这样的模板:

template <typename Container>
typename Container::const_iterator constify(const Container &, typename Container::iterator it) {
    return it;
}

然后你可以像这样强制模板推导:

std::distance(constify(v, it), cit);

而不是写出那种很长的字体。Container&参数是一个遗憾,因为AFAIKContainer不能单独从迭代器参数中推导出来。

std::distance将与这两个迭代器一起工作,但不起作用的是模板参数推断。编译器正试图解决用什么类型来代替第一个模板参数,并且有两个潜在的候选者,根据标准,这两个候选者最终都会失败。

您可以做两件事中的一件,要么只比较相同类型的迭代器,要么将类型提供给模板:

std::distance<std::vector<int>::const_iterator>( v.begin(), v.cbegin() );