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.
What am I doing wrong, as I am pretty sure that find_if accepts const_iterator type arguments?
EDIT
If this is the issue of i being a const_iterator and input.end() being an iterator, why does the following code work? This is from 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; 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. That's not the same type as the const iterator '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().
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With