简体   繁体   English

find_if不使用const_iterator

[英]find_if not working with const_iterator

I wrote this program: 我写了这个程序:

// splits a sentence into words
#include <iostream>
#include <string>
#include <algorithm>
#include "spacefunc.h"

using std::string;
using std::cout;
using std::endl;
using std::find_if;

int main() {
    typedef string::const_iterator iter;

    string input = "This is me";
    iter i = input.begin();

    while (i != input.end()) {
        iter j;

        i = find_if(i, input.end(), notspace);
        j = find_if(i, input.end(), is_space);

        cout << string(i, j) << endl;

        i = j;
    }   

    return  0;  
}

It fails with following errors: 它失败并出现以下错误:

word_splitter.cpp: In function ‘int main()’:
word_splitter.cpp:21:45: error: no matching function for call to ‘find_if(iter&, std::__cxx11::basic_string<char>::iterator, bool (&)(char))’
         i = find_if(i, input.end(), notspace);
                                             ^
In file included from /usr/include/c++/5/algorithm:62:0,
                 from word_splitter.cpp:4:
/usr/include/c++/5/bits/stl_algo.h:3806:5: note: candidate: template<class _IIter, class _Predicate> _IIter std::find_if(_IIter, _IIter, _Predicate)
     find_if(_InputIterator __first, _InputIterator __last,
     ^
/usr/include/c++/5/bits/stl_algo.h:3806:5: note:   template argument deduction/substitution failed:
word_splitter.cpp:21:45: note:   deduced conflicting types for parameter ‘_IIter’ (‘__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >’ and ‘__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >’)
         i = find_if(i, input.end(), notspace);
                                             ^
word_splitter.cpp:22:45: error: no matching function for call to ‘find_if(iter&, std::__cxx11::basic_string<char>::iterator, bool (&)(char))’
         j = find_if(i, input.end(), is_space);
                                             ^
In file included from /usr/include/c++/5/algorithm:62:0,
                 from word_splitter.cpp:4:
/usr/include/c++/5/bits/stl_algo.h:3806:5: note: candidate: template<class _IIter, class _Predicate> _IIter std::find_if(_IIter, _IIter, _Predicate)
     find_if(_InputIterator __first, _InputIterator __last,
     ^
/usr/include/c++/5/bits/stl_algo.h:3806:5: note:   template argument deduction/substitution failed:
word_splitter.cpp:22:45: note:   deduced conflicting types for parameter ‘_IIter’ (‘__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >’ and ‘__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >’)
         j = find_if(i, input.end(), is_space);

If I change i, j to iterator type, it compiles. 如果我将i, j更改为iterator类型,则编译。

What am I doing wrong, as I am pretty sure that find_if accepts const_iterator type arguments? 我做错了什么,因为我很确定find_if接受const_iterator类型的参数?

EDIT If this is the issue of i being a const_iterator and input.end() being an iterator , why does the following code work? 编辑如果这是i作为const_iterator和input.end()作为iterator ,为什么以下代码有效? This is from Accelerated C++ . 这来自Accelerated C++

vector < string > split(const string & str) {
  typedef string::const_iterator iter;
  vector < string > ret;
  iter i = str.begin();
  while (i != str.end()) {
    // ignore leading blanks
    i = find_if(i, str.end(), not_space);
    // find end of next word
    iter j = find_if(i, str.end(), space);
    // copy the characters in [i, j)
    if (i != str.end())
      ret.push_back(string(i, j));
    i = j;
  }
  return ret;
}

find_if accepts non-const iterators and const_iterators; find_if接受非const迭代器和const_iterators; however, the iterators that you pass to it have to be the same type. 但是,传递给它的迭代器必须是相同的类型。 The problem here is that input.end() returns a non-const iterator, because input is not a const object. 这里的问题是input.end()返回一个非const迭代器,因为input不是const对象。 That's not the same type as the const iterator 'i'. 这与const迭代器'i'的类型不同。 To get a const end iterator for a non-const object (or for a const object, but that's a distraction), use input.cend() . 要获得非const对象的const结束迭代器(或对于const对象,但这是一个分心),请使用input.cend()

find_if 's signature looks like this: find_if的签名如下:

 template<class InputIt, class UnaryPredicate> InputIt find_if(InputIt first, InputIt last, UnaryPredicate p); 

It expects its first 2 arguments to be of the same type. 它希望它的前两个参数属于同一类型。 With find_if(i, input.end(), notspace) , if i is a string::const_iterator , it's not the same type as input.end() which would be a string::iterator since input is non-const. 使用find_if(i, input.end(), notspace) ,如果i是一个string::const_iterator ,它与input.end()类型不同,它是一个string::iterator因为input是非const的。 If input was a const std::string , input.end() would return a string::const_iterator 如果inputconst std::string ,则input.end()将返回string::const_iterator


Post C++11, it's uncommon to see a typedef string::const_iterator iter . 在C ++ 11之后,看到一个typedef string::const_iterator iter并不常见。 Use of auto is more common: 使用auto更常见:

string input = "This is me";
auto i = input.begin();

Others have explained why you experienced a compilation error. 其他人已经解释了为什么遇到编译错误。 In my view, future mistakes can be avoided if you express more directly your "ultimate" intention, and let automatic type deduction take care of the rest. 在我看来,如果你更直接地表达你的“终极”意图,可以避免未来的错误,让自动类型演绎处理其余的事情。 For example: if you want your input to be immutable, use const to mark it as such, and let auto take care of the rest. 例如:如果您希望输入是不可变的,请使用const将其标记为,并让auto处理其余内容。

#include <cctype>
#include <iostream>
#include <algorithm>
#include <string>

bool is_space(char c) { return std::isspace(c); }
bool is_not_space(char c) { return not is_space(c); }

int main() {
  const std::string input{"This is me"};

  for (auto it = input.begin(); it != input.end();) {

    it = std::find_if(it, input.end(), is_not_space);
    auto it_end = std::find_if(it, input.end(), is_space);

    std::cout << std::string(it, it_end) << "\n";

    it = it_end;
  }
}

Sample run: 样品运行:

$ clang++ example.cpp -std=c++17 -Wall -Wextra
$ ./a.out 
This
is
me

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM