std::ranges::min() algorithm
- since C++20
- Simplified
- Detailed
// (1)
constexpr const T&
min( const T& a, const T& b, Comp comp = {}, Proj proj = {} );
// (2)
constexpr const T
min( std::initializer_list<T> r, Comp comp = {}, Proj proj = {} );
// (3)
constexpr ranges::range_value_t<R> min( 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>>
// (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&
min( 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
min( 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> min( R&& r, Comp comp = {}, Proj proj = {} );
Returns the smaller of the given projected elements.
-
(1) Returns the smaller of
a
andb
. -
(2) Returns the first smallest element in the initializer list
r
. -
(3) Returns the first smallest 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 smaller of
a
andb
, according to the projection. If they are equivalent, returnsa
. - (3 - 4) The smallest 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) - 1
comparisons.
Exceptions
(none)
Possible implementation
min(1) and min(2)
struct min_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, b), std::invoke(proj, a)) ? 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::min_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::min_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, *i), std::invoke(proj, m)))
m = *i;
return m;
}
}
};
inline constexpr min_fn min;
Notes
Capturing the result of std::ranges::min
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::min(n - 1, n + 1); // r is dangling
Examples
#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: 1
smaller of 'a', and 'b': 'a'
shortest of "foo", "bar", and "hello": "foo"
Hover to see the original license.