Why hasn't C++ standardized overloads of algorithms which operate on entire containers?

Viewed 131

Standard ISO C++ has a rich algorithm library including plenty of syntactic sugar like std::max_element, std::fill, std::count, etc.

I'm having a hard time understanding why ISO saw fit to standardize many such trivial algorithms, yet not overloads of algorithms which operate on whole containers.

I don't really understand why they added such basic things when we're left without whole container versions (surely by far the most common case) or similarly left with the atrocity that is the vector erase-remove idiom:

v.erase(std::remove(v.begin(), v.end(), elem), v.end());

It seems that every project I write in C++, I end up including my own custom header file which includes basic syntactic sugar for things like this.

Of course, any of the trivial whole-container overloads could be included in a custom header. That's also true of the many of the simple algorithms which were standardized.

What I'm trying to understand is why there's a good reason for things in the standard like std::max_element and std::fill on ranges, but not versions that operate on whole containers, or for other syntactic sugar that reduces the verbosity of writing C++ code.

2 Answers

That has been rectified in C++20

See one example on cppreference

template< ranges::input_range R, class Proj = std::identity,
          std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>, Proj>> Pred >
constexpr ranges::range_difference_t<R>
  count_if( R&& r, Pred pred = {}, Proj proj = {} );

bool is_even(int n) {
   return (n % 2 == 0);
}
std::vector<int> l(10);
std::iota(l.begin(), l.end(), 0); // is in numerics which hasn't been rangified.

auto cnt = std::ranges::count_if(arr, is_even);

Why hasn't C++ standardized overloads of algorithms which operate on entire containers?

The answer is same as to answer to all questions like this: Such overloads haven't been standardised either because such change hasn't been proposed or such proposal hasn't been accepted. The original STL didn't have such overloads.

An answer to a similar question links to a blog post which has an argument for why such overload would be problematic for some algorithms which may be part of the reason why such overloads weren't part of the original design nor have been introduced later. In short, they would introduce ambiguity and misleading error messages.


Instead of overloads, C++ does however have the same algorithms for full ranges in a separate namespace std::ranges since C++20. An example using fill:

std::ranges::fill(container, value);

atrocity that is the vector erase-remove idiom

Although ranges don't introduce new member function overloads, there is a non-member alternative for erasure:

std::erase(vector, elem);
Related