2012-03-08 47 views
11

像问题所述,我想知道原因。因为当我尝试获取const与非const迭代器之间的距离时出现错误。为什么std :: distance对const和nonconst迭代器的混合不起作用?

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

从我对迭代器的有限理解中,我没有看到为什么它不应该工作。

回答

19

在调用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); 
6

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

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

因此,firstlast必须转换为同一类型和模板分辨率遗憾的是没有考虑vector<int>::iterator可转换为vector<int>::const_iterator

+0

嗯为什么不他们只是用2模板参数创建模板?是否有可能在cpp core lang中执行?我所要求的是设计决定还是语言限制? – NoSenseEtAl 2012-03-08 18:17:59

+0

要清楚,我知道他们可以用2个模板参数制作模板,但是我想知道它会与1个模板参数版本 – NoSenseEtAl 2012-03-08 18:18:55

+0

@NoSenseEtAl发生冲突,我会说设计决定。这样做更简单,并且计算不同种类的迭代器(例如,一个随机访问迭代器和一个前向迭代器)之间的距离可能不是您想要经常执行的操作。你确实可以用两个模板参数来编写一个版本,但是解决什么现实世界的问题呢? – 2012-03-08 18:23:10

3

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

你可以做两件事情之一,无论是只比较同类型的迭代器,或提供类型的模板:由于大家都说

std::distance<std::vector<int>::const_iterator>(v.begin(), v.cbegin()); 
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不能从一个迭代器参数推导出来。

相关问题