[英]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
如果
input
是const 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.