为什么std :: distance不能用于const和非const迭代器的混合?

时间:2012-03-08 17:46:06

标签: c++ c++11 iterator

就像问题所说,我想知道原因。因为当我试图获得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> >&)

根据我对迭代器的有限理解,我认为没有理由不这样做。

4 个答案:

答案 0 :(得分:20)

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 );

答案 1 :(得分:6)

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

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

因此,firstlast必须可转换为相同的类型,但遗憾的是,模板解析不会认为vector<int>::iterator可转换为vector<int>::const_iterator

答案 2 :(得分:4)

正如大家所说,这是因为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&参数很遗憾,因为AFAIK Container不能仅从迭代器参数中推断出来。

答案 3 :(得分:3)

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

您可以执行以下两种操作之一,或者仅比较相同类型的迭代器,或者为模板提供类型:

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