std::ranges::max() algorithm
- since C++20
- Simplified
- Detailed
// (1)constexpr const T& max( const T& a, const T& b, Comp comp = {}, Proj proj = {} );// (2)constexpr const T max( std::initializer_list<T> r, Comp comp = {}, Proj proj = {} );// (3)constexpr ranges::range_value_t<R> max( R&& r, Comp comp = {}, Proj proj = {} );The type of arguments are generic and have the following constraints:
T- (none)Proj- (none)Comp- (none)
The Proj and Comp template arguments have, the following default types for all overloads: std::identity, ranges::less.
Additionally, each overload has the following constraints:
- (1) -
indirect_strict_weak_order<Comp, projected<const T*, Proj>> - (2) -
indirect_strict_weak_order<Comp, projected<const T*, Proj>> - (3) -
indirectly_copyable_storable<ranges::iterator_t<R>, ranges::range_value_t<R>*> && indirect_strict_weak_order<Comp, projected<ranges::iterator_t<R>, Proj>>
(The std:: namespace was ommitted here for readability)
// (1)template< class T, class Proj = std::identity, class Comp = ranges::less> requires std::indirect_strict_weak_order<Comp, std::projected<const T*, Proj>>constexpr const T& max( const T& a, const T& b, Comp comp = {}, Proj proj = {} );// (2)template< std::copyable T, class Proj = std::identity, class Comp = ranges::less> requires std::indirect_strict_weak_order<Comp, std::projected<const T*, Proj>>constexpr const T max( std::initializer_list<T> r, Comp comp = {}, Proj proj = {} );// (3)template< ranges::input_range R, class Proj = std::identity, class Comp = ranges::less> requires std::indirectly_copyable_storable<ranges::iterator_t<R>, ranges::range_value_t<R>*> && std::indirect_strict_weak_order<Comp, std::projected<ranges::iterator_t<R>, Proj>>constexpr ranges::range_value_t<R> max( R&& r, Comp comp = {}, Proj proj = {} );Returns the greater of the given projected elements.
-
(1) Returns the greatest of
aandb. -
(2) Returns the first greatest element in the initializer list
r. -
(3) Returns the first greatest value in the range
r.
The function-like entities described on this page are niebloids.
Parameters
a b | The values to compare. |
r | The range of values to compare. |
comp | Comparison to apply to the projected elements. |
proj | Projection to apply to the elements. |
Return value
- (1) The greater of
aandb, according to the projection. If they are equivalent, returnsa. - (3 - 4) The greatest element in
r, according to the projection. If several values are equivalent to the smallest, returns the leftmost one.
If the range is empty (as determined by ranges::distance(r)), the behavior is undefined.
Complexity
- (1) Exactly one comparison.
- (3 - 4) Exactly
ranges::distance(r) - 1comparisons.
Exceptions
(none)
Possible implementation
max(1) and max(2)
struct max_fn{ template<class T, class Proj = std::identity, std::indirect_strict_weak_order< std::projected<const T*, Proj>> Comp = ranges::less> constexpr const T& operator()(const T& a, const T& b, Comp comp = {}, Proj proj = {}) const { return std::invoke(comp, std::invoke(proj, a), std::invoke(proj, b)) ? b : a; } template<std::copyable T, class Proj = std::identity, std::indirect_strict_weak_order< std::projected<const T*, Proj>> Comp = ranges::less> constexpr const T operator()(std::initializer_list<T> r, Comp comp = {}, Proj proj = {}) const { return *ranges::max_element(r, std::ref(comp), std::ref(proj)); } template<ranges::input_range R, class Proj = std::identity, std::indirect_strict_weak_order< std::projected<ranges::iterator_t<R>, Proj>> Comp = ranges::less> requires std::indirectly_copyable_storable<ranges::iterator_t<R>, ranges::range_value_t<R>*> constexpr ranges::range_value_t<R> operator()(R&& r, Comp comp = {}, Proj proj = {}) const { using V = ranges::range_value_t<R>; if constexpr (ranges::forward_range<R>) return static_cast<V>(*ranges::max_element(r, std::ref(comp), std::ref(proj))); else { auto i = ranges::begin(r); auto s = ranges::end(r); V m(*i); while (++i != s) if (std::invoke(comp, std::invoke(proj, m), std::invoke(proj, *i))) m = *i; return m; } }};inline constexpr max_fn max;Notes
Capturing the result of std::ranges::max by reference produces a dangling reference if one of the parameters is a temporary and that parameter is returned:
int n = 1;const int& r = std::ranges::max(n - 1, n + 1); // r is danglingExamples
#include <algorithm>#include <iostream>#include <string>int main(){ namespace ranges = std::ranges; using namespace std::string_view_literals; std::cout << "smaller of 1 and 9999: " << ranges::min(1, 9999) << '\n' << "smaller of 'a', and 'b': '" << ranges::min('a', 'b') << "'\n" << "shortest of \"foo\", \"bar\", and \"hello\": \"" << ranges::min({ "foo"sv, "bar"sv, "hello"sv }, {}, &std::string_view::size) << "\"\n";}smaller of 1 and 9999: 1smaller of 'a', and 'b': 'a'shortest of "foo", "bar", and "hello": "foo"Hover to see the original license.