Reputation: 4804
I have a simple program that calls std::find_if
, I think I've pass the first two argument as iterator and the third as a predict, however the code still won't compile, any ideas?
#include <string>
#include <cctype>
#include <algorithm>
bool notspace(char ch);
bool space(char ch);
int main() {
typedef std::string::const_iterator iter;
iter i;
std::string s = "ab c";
i = std::find_if(i, s.end(),space);
return 0;
}
bool space(char ch) {
return std::isspace(ch);
}
Error message:
q-isspace.cpp: In function ‘int main()’:
q-isspace.cpp:12:38: error: no matching function for call to ‘find_if(iter&, std::__cxx11::basic_string<char>::iterator, bool (&)(char))’
i = std::find_if(i, s.end(),space);
^
In file included from /usr/include/c++/5/algorithm:62:0,
from q-isspace.cpp:3:
/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:
q-isspace.cpp:12:38: 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 = std::find_if(i, s.end(),space);
Upvotes: 4
Views: 5047
Reputation: 1393
i
variable is not initialized. The more elegent way to code is to use lambda function as given below.
#include <string>
#include <cctype>
#include <algorithm>
int main() {
typedef std::string::const_iterator iter;
iter i,j;
std::string s = "ab c";
i = std::find_if(s.begin(), s.end(),[](char ch) { return std::isspace(ch); } );
j = std::find_if(s.begin(), s.end(),[](char ch) { return !std::isspace(ch); } );
return 0;
}
Upvotes: 1
Reputation: 36513
If you want to know why your compilation errors, it's because std::find_if
only has 1 template parameter. s.end()
is a normal iterator while i
is a const_iterator
, those don't match up. And then there's the problem with i
being uninitialized which will cause you a runtime error. Just use s.begin()
:
i = std::find_if(s.begin(), s.end(),space);
If you want to be able to change contents through i
, you should make it a normal iterator:
typedef std::string::iterator iter;
Upvotes: 3
Reputation: 16864
int main() {
typedef std::string::const_iterator iter;
iter i,j;
std::string s = "ab c";
i = std::find_if(i, s.end(),notspace);
j = std::find_if(i, s.end(),space);
return 0;
}
You're not initalising your i
variable, so it is not pointing to anything. This means that [i, s.end())
does not form a valid range, so your call to find_if()
will not work correctly.
Try this instead:
i = std::find_if(s.begin(), s.end(), notspace);
Upvotes: 6
Reputation: 170279
You pass i
which is of type std::string::const_iterator
(and also uninitialized) as first parameter to std::find_if
. Then you pass s.end()
which returns a std::string::iterator
. The two iterators are of different types, while std::find_if
expects them to be of the same type.
The correct rule of thumb, is to pair the calls to begin()
and end()
#include <string>
#include <cctype>
#include <algorithm>
bool notspace(char ch);
bool space(char ch);
int main() {
typedef std::string::const_iterator iter;
iter i,j;
std::string s = "ab c";
i = std::find_if(s.begin(), s.end(),notspace);
j = std::find_if(s.begin(), s.end(),space);
return 0;
}
bool space(char ch) {
return std::isspace(ch);
}
bool notspace(char ch) {
return !std::isspace(ch);
}
Upvotes: 8
Reputation: 76523
iter i,j;
std::string s = "ab c";
i = std::find_if(i, s.end(),notspace);
This calls std::find_if
with a default-initialized iterator as its first argument. That iterator has no relation to any iterator into s
, so the result will be nonsense. Change the call to
`std::find_if(s.begin(), s.end(), notspace);
And make the analogous change in the other call.
Upvotes: 3