std::ranges::max
From cppreference.com
| Defined in header <algorithm>
|
||
| Call signature |
||
template< class T, class Proj = std::identity,
std::indirect_strict_weak_order
<std::projected<const T*, Proj>> Comp = ranges::less >
constexpr const T&
max( const T& a, const T& b, Comp comp = {}, Proj proj = {} );
|
(1) | (since C++20) |
template< std::copyable T, class Proj = std::identity,
std::indirect_strict_weak_order
<std::projected<const T*, Proj>> Comp = ranges::less >
constexpr T
max( std::initializer_list<T> r, Comp comp = {}, Proj proj = {} );
|
(2) | (since C++20) |
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>
max( R&& r, Comp comp = {}, Proj proj = {} );
|
(3) | (since C++20) |
template< /*execution-policy*/ Ep, /*sized-random-access-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>*>
ranges::range_value_t<R>
max( Ep&& policy, R&& r, Comp comp = {}, Proj proj = {} );
|
(4) | (since C++26) |
For the definition of /*execution-policy*/, see this page; for the definition of /*sized-random-access-range*/, see this page.
Returns the greater of the given values (projected by proj), the projected values are compared using comp.
1) Returns the greater of
a and b.2-4) Returns the first greatest value in the initializer list or target range
r. If
ranges::distance(r) is zero, the behavior is undefined.4) Same as (3), but executed according to
policy.The function-like entities described on this page are algorithm function objects (informally known as niebloids), that is:
- Explicit template argument lists cannot be specified when calling any of them.
- None of them are visible to argument-dependent lookup.
- When any of them are found by normal unqualified lookup as the name to the left of the function-call operator, argument-dependent lookup is inhibited.
Parameters
| a, b | - | the values to compare |
| r | - | the range of values to compare |
| comp | - | the comparator to be applied to the (projected) elements |
| proj | - | the projection to be applied to the elements |
| policy | - | the execution policy to use |
Return value
1) The greater of
a and b, according to their respective projected values. If they are equivalent, returns a.2-4) The greatest value in
r, according to the projection. If there are multiple greatest values, returns the first one of them.Complexity
1) Exactly one application of
comp, and two applications of proj.2-4) Given N as
ranges::distance(r):2,3) Exactly N-1 applications of
comp, and twice as many applications of proj.4) 𝓞(N) applications of
comp, and twice as many applications of proj.Exceptions
4) During the execution process:
- If the temporary memory resources required for parallelization are not available, std::bad_alloc is thrown.
- If an uncaught exception is thrown while accessing objects via an algorithm argument, the behavior is determined by the execution policy (for standard policies, std::terminate is invoked).
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 + 2, n * 2); // r is dangling
Possible implementation
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 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;
|
Example
Run this code
#include <algorithm>
#include <iostream>
#include <string>
static_assert(std::ranges::max({0B10, 0X10, 010, 10}) == 16); // overload (2)
int main()
{
namespace ranges = std::ranges;
using namespace std::string_view_literals;
std::cout << "Larger of 1 and 9999: " << ranges::max(1, 9999) << '\n'
<< "Larger of 'a' and 'b': '" << ranges::max('a', 'b') << "'\n"
<< R"(Longest of "foo", "bar", and "hello": )"
<< ranges::max({"foo"sv, "bar"sv, "hello"sv}, {},
&std::string_view::size) << "\"\n";
}
Output:
Larger of 1 and 9999: 9999
Larger of 'a' and 'b': 'b'
Longest of "foo", "bar", and "hello": "hello"
See also
| returns the greater of the given values (function template) | |
(C++20) |
returns the smaller of the given values (algorithm function object) |
(C++20) |
returns the smaller and larger of two elements (algorithm function object) |
(C++20) |
returns the largest element in a range (algorithm function object) |
(C++20) |
clamps a value between a pair of boundary values (algorithm function object) |