0

I frequently find myself using std algorithms that depend on a begin iterator and an end iterator. Why doesn't the standard include overloads that take the container as the argument (rather than the iterators). Is there a technical reason for not including something like this in the standard?

template <typename ContainerT, typename ValueT>
typename ContainerT::iterator find(ContainerT& container, const ValueT& value)
{
    return std::find(begin(container), end(container), value);
}

This is very convenient when searching whole vectors. I realize the explicit iterator version is still needed in case you don't want to iterate over the entire container.

std::vector<std::string> v;
v.push_back("foo");
v.push_back("bar");

std::find(v.begin(), v.end(), "bar");

find(v, "bar"); // much nicer! :)
pqvst
  • 4,344
  • 6
  • 33
  • 42
  • 1
    You still need to have access to the container's `end()` function to make sense of the result. All in all, there's very little to be gained from this. There's already *one* good set of tools in the library, and you're welcome to construct whatever shorthands you find useful for your project yourself. – Kerrek SB Dec 08 '13 at 15:46
  • Hopefully one day it'll be possible, in the mean time I'll continue using my own "ranged" versions... – Matthieu M. Dec 08 '13 at 16:30

3 Answers3

2

See here for a good answer: STL algorithms: Why no additional interface for containers (additional to iterator pairs)?

(apologies, I cannot mark as duplicate)

Community
  • 1
  • 1
0

It won't work on arrays. For example:

int myArray* = new int[2354];

begin(myArray) and end(myArray) don't mean much. but std::find(myArray, myArray + 2354, value) would work.

But with the standard does allow it to work on arrays properly with the current interface.

Besides, you dont always want to us the algorithm on the entire container.

It only works in the interval between 2 iterators, so you could just use find() on something form the beginning till the middle of the container for example.

Yochai Timmer
  • 48,127
  • 24
  • 147
  • 185
  • 1
    It would work perfectly for arrays, just not for pointers. Besides that the OP especially stated that he doesn't want the additional overloads to replace but extend the existing functions. Of course the iterator version is still needed (I'm not saying the additional overloads would be required or any useful, just that the answer doesn't really address the question). – Christian Rau Dec 08 '13 at 16:16
0

I'm surprised no one has mentioned the Boost Range library yet. It provides the functionality that you're looking for, and there are proposals to add something similar to the STL. There may even be a ISO C++ working group dedicated to ranges, but I can't remember off the top of my head.

Also, this is one of the rare instances where I don't agree with Kerrek SB. There is a lot of utility to be gained from raising the level of abstraction from iterators to ranges, in particular the use of adaptors to modify ranges before executing algorithms on them. The Boost range library explains why this is such an important idea. As a short example, consider a range of pointers where you want to access the referents. To do that with iterators, you need to do something like the following:

std::vector<int *> v; // populate with something.

auto begin = boost::make_indirect_iterator(v.begin());
auto end   = boost::make_indirect_iterator(v.end  ());

std::for_each(begin, end, do_something);

Using range algorithms and adaptors we can express this much more succinctly and, I think, clearly:

boost::range::for_each(v | boost::adaptors::indirected, do_something);

The only thing that seems to be lacking from the current Boost implementation is that range adaptors like transformed and filtered don't yet play nice with lambda functions. Not a bid hit against a library that has radically changed the way I code.

Chris Hayden
  • 1,104
  • 6
  • 6