如何在基于范围的循环中使用 std::distance?

How do you use std::distance in a range-based loop?

这是我无法编译的代码:

for( auto occurances : occ ){
  if( occurances == 1 )
    cout << distance( occ.begin(), occurances )
}

它给了我以下错误:

candidate template ignored: deduced conflicting types for parameter '_InputIter' 
('std::__wrap_iter<int *>' vs. 'int')

这是我第五次遇到这个错误。每次,经过一些研究和挫折后,我就放弃并使用基本的 for 循环。这里的问题是我懒得写像这样的基本for循环:

for( size_t occurances = 0; occurances < occ.size(); occurances++ ){
  if( occ[ occurances ] == 1 )
    // do something with size_t occurances
}

我试图在 occ.begin() 前面插入一个 *(我不太了解指针)。错误改为:

candidate template ignored: substitution failure [with _InputIter = int]: no type 
named 'difference_type' in 'std::iterator_traits<int>'
distance(_InputIter __first, _InputIter __last)

我该如何解决这个问题?谢谢大家的回答,真的很感激。抱歉,如果这是一个重复的问题,我真的找不到答案。

您可以自己计算循环的迭代次数:

size_t loop_count = 0;
for( auto occurances : occ ){
  if( occurances == 1 )
    cout << loop_count;
  ++loop_count;
}

但这并不比直接编写 for 循环更容易,而且您可能会忘记计算计数器。


好的,因为 OP 有兴趣对向量执行此操作,这里有一个适用于 std::vectorstd::string ONLY 的解决方案。它之所以有效,是因为对于这些容器,operator[] returns 对与您传入的索引对应的元素或字符的引用,并且获取该地址是合法的(并且在这里很有用)参考。

由于现在这些容器都保证连续存储,所以你可以直接用这种方式得到的两个地址的差值来得到你想要的。

这是一个简单的例子:

#include <iostream>
#include <string>
#include <vector>

int main()
{
    std::string s = "abcde";
    std::vector <int> v ( { 100, 101, 102, 103, 104 } );

    for (const auto &c : s)
    {
        if (c == 'c')
            std::cout << &c - &s [0] << "\n";
    }

    for (const auto &e : v)
    {
        if (e == 103)
            std::cout << &e - &v [0] << "\n";
    }
}

输出:

2
3

请注意,如评论中所述,您需要使用 auto &,而不仅仅是 auto,因为 auto 将副本传递到循环中,这会破坏整个循环想法。

Live demo.