2

Several algorithms in the C++ STL require to specify explicitly two iterators. For example, sorting a std::vector<T> v is done with std::sort(v.begin(), v.end()). Since processing the entire container (e.g. with std::sort, std::find, etc.) is a fairly common situation, I'm wondering why a simple version of these algorithms that accepts just the container is not implemented. I mean something like std::sort(v), that uses v.begin() and v.end() iterators by default.

Is there some underlying technical reason that I'm not aware of? Thank you in advance.

4
  • 1
    It's possible since C++20 with ranges: en.cppreference.com/w/cpp/algorithm/ranges/sort. Commented Apr 21, 2021 at 8:04
  • The use of iterators makes the functions more portable with more containers. If you make your own container with a fully functional iterator, it will automatically work with functions like std::sort. Commented Apr 21, 2021 at 8:06
  • By using iterator pairs it's also possible to use these function with pointers (and arrays). Commented Apr 21, 2021 at 8:07
  • iterators are not necesarrily bound to a container. Commented Apr 21, 2021 at 8:33

1 Answer 1

2

I'm wondering why a simple version of these algorithms that accepts just the container is not implemented.

It was, in C++20, with std::ranges versions.

Is there some underlying technical reason that I'm not aware of?

Sort of. When the algorithms in <algorithm> were first proposed, distinguishing between different cases in templates was possible, but it was rather unwieldy.

How do you distinguish, from the call site, which of these templates fits?

template <typename InIt, typename OutIt, typename Func>
OutIt transform(InIt, InIt, OutIt, Func); // unary transform on iterator

template <typename Lhs, typename Rhs, typename OutIt, typename Func>
OutIt transform(Lhs, Rhs, OutIt, Func); // binary transform on containers
Sign up to request clarification or add additional context in comments.

11 Comments

also by concept of iterators it's impossible to get end() from iterator returned by begin(), so whole range function wouldn't have same semantic as begin-end one, e.g. sort(container) vs. sort(begin_iterator, end_iterator), and the former wouldn't be applicable to arrays\pointers. Perhaps author of original STL (Morozov) deemed such inconsistency confusing. ISO just followed the pre-existing library
@Swift-FridayPie? I don't follow. The container overload of sort would be defined "equivalent to sort(begin(container), end(container))"
you can DO that now, but SHOULD you do that while designing an API that can be understood and code created would be transparent to someone who is less familiar with every overload? Library was designed in times when C++ wasn't standardized, sizeof behavior was slightly different too. And there was no std::begin, std::end in STL. Array version of sort operation on array arr would be sort(arr, arr + size_of_array). Should it be a C-style, sort(arr, size_of_array)? You can say that design of those functions is historical. ranges library appeared as attempt to rewrite rules.
std::begin, std::end are introduced in ISO C++11 and even in that time some implementation didn't overload them for arrays btw.
@Swift-FridayPie the array case would be the easiest to distinguish. sort(T(&arr)[N]) would be defined as sort(arr, arr+N). I wasn't talking about users having to distinguish, I was talking about writing the overloads with C++98 era tools such that there aren't ambiguous call sites.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.