开发者

STL algorithms and const_iterators

开发者 https://www.devze.com 2022-12-09 19:25 出处:网络
Today I wrote a small predicate to find matching symbols in a container. But I\'m faced to a problem: I want to use this predicate in a std::find_if call inside a const-method of a class, searching i

Today I wrote a small predicate to find matching symbols in a container.

But I'm faced to a problem: I want to use this predicate in a std::find_if call inside a const-method of a class, searching in a container that is a member of this class.

But I just noticed that neither std::find nor std::find_if are able to operate on const_iterators !

I checked on some C++ references and it seems there is no version of std::find or std::find_if that accept/return const_iterators. I just can't understand why, since from what I've seen, there is no way that these algorithms could modify the object referenced by the iterator.

Here is how is documented std::find in the SGI implementation:

Returns the first iterator i in the range [first, last) such that *i == value. Retur开发者_StackOverflow中文版ns last if no such iterator exists.


std::find and std::find_if can definitely operate on *::const_iterator for a given container. Are you by chance looking at the signatures of those functions, and misunderstanding them?

template <class InputIterator, class Type>
InputIterator find(InputIterator first, InputIterator last, const Type& val);

Note that InputIterator here is just a name of a template type parameter, and any const_iterator will satisfy the requirements for it.

Or, perhaps, you're confusing const_iterator (i.e. an iterator referencing a const value) with a const iterator (i.e. an iterator which is itself const)?


std::find and std::find_if both take the iterator type as a template parameter, so they most certainly can operate on const_iterators. Just for a quick example:

#include <vector>
#include <algorithm>
#include <iostream>
int main() { 
    std::vector<int> x;

    std::fill_n(std::back_inserter(x), 20, 2);
    x.push_back(3);

    std::vector<int>::const_iterator b = x.begin();
    std::vector<int>::const_iterator e = x.end();

    std::vector<int>::const_iterator p = std::find(b, e, 3);

    std::cout << *p << " found at position: " << std::distance(b, p) << "\n";
    return 0;
}

This should be accepted by any properly functioning C++ compiler, and produce results like:

3 found at position: 20


I have just had the same problem. I had a member function that was calling find_if on a member vector, and the compiler gave me an error when I tried making the member function const. It turned out that this was because I was assigning the return value of find_if to an iterator instead of const_iterator. The caused the compiler to assume that the parameters of find_if must also be iterator instead of const_iterator, which it could not get from the const member vector.


If by any chance you are here for the same reason as me:

error: no matching function for call to ‘find(std::vector<int>::const_iterator, std::vector<int>::const_iterator, int)’

It doesn't have anything to do with const_iterators. You probably just forgot to #include <algorithm> :-)


I just had an issue with this code:

std::string str;
std::string::const_iterator start = str.begin();
std::string::const_iterator match = std::find(start, str.end(), 'x');

The error was "no matching overload for std::find".

The fix I needed was to use cend(). It's confusing that cbegin() isn't required, I'm not sure why that conversion is okay (implicitly) and not for the end() as a function parameter.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号