Yue Wang
Yue Wang

Reputation: 1750

What type does std::find_if_not() return?

I'm stuck when doing an exercise from the book C++ Primer , which goes:

Exercise 10.24:Use bind and check_size to find the first element in a vector of ints that has a value greater than the length of a specified string value.

My code:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>

bool check_size(const std::string &s, std::string::size_type sz)
{
   return s.size() > sz;
}

std::vector<int>::iterator
find_first_bigger(const std::vector<int> &v, const std::string &s);

int main(){return 0;}

std::vector<int>::iterator
find_first_bigger(const std::vector<int> &v, const std::string &s)
{
    auto it= std::find_if_not(v.begin(), v.end(),std::bind(check_size,s,std::placeholders::_1));
    return it;
}

When trying to compile, the compiler complained that:

error: could not convert 'it' from '__gnu_cxx::__normal_iterator<const int*, std::vector<int> >' to 'std::vector<int>::iterator {aka __gnu_cxx::__normal_iterator<int*, std::vector<int> >}'

To find out what is going on,I turned to the header *stl_algo.h* in which I guess std::find_if_not is defined.The comment there said:

@return The first iterator @c i in the range @p [_first,_last)

The definition of this function:

template<typename _InputIterator, typename _Predicate>
inline _InputIterator
find_if_not(_InputIterator __first, _InputIterator __last,
    _Predicate __pred)
{
  // concept requirements
  __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
  __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
      typename iterator_traits<_InputIterator>::value_type>)
  __glibcxx_requires_valid_range(__first, __last);
  return std::__find_if_not(__first, __last, __pred);
}

It seems the return type should be the same to the argument.But why complier complained so? How to fix this error?Thx.

Upvotes: 2

Views: 1393

Answers (2)

nos
nos

Reputation: 229234

std::vector<int>::iterator
find_first_bigger(const std::vector<int> &v, const std::string &s);
                   ^^

Your vector is const. So you'll get a std::vector<int>::const_iterator. Had it not been const, you'd get a std::vector<int>::iterator

Upvotes: 4

doctorlove
doctorlove

Reputation: 19272

Notice

//...
inline _InputIterator
find_if_not(_InputIterator __first, _InputIterator __last,
    _Predicate __pred)
//...

returns the same type of iterator that it receives as a parameter.

Since you passed a const std::vector<int> &v you must return a const_iterator thus

std::vector<int>::const_iterator
find_first_bigger(const std::vector<int> &v, const std::string &s);

Upvotes: 3

Related Questions