std::ranges::min() 算法
- 自 C++20 起
- 简化
- 详细
// (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 = {} );
参数类型是泛型的,并具有以下约束
T
- (无)Proj
- (无)Comp
- (无)
Proj
和 Comp
模板参数对于所有重载都具有以下默认类型:std::identity
、ranges::less
。
此外,每个重载都有以下约束
- (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 = {} );
返回给定投影元素中较小的一个。
-
(1) 返回
a
和b
中较小的一个。 -
(2) 返回初始化列表
r
中第一个最小的元素。 -
(3) 返回范围
r
中第一个最小的值。
本页描述的函数类实体是niebloids。
参数
a b | 要比较的值。 |
r | 要比较的值范围。 |
comp | 应用于投影元素的比较。 |
proj | 应用于元素的投影。 |
返回值
- (1) 根据投影,返回
a
和b
中较小的一个。如果它们等价,则返回a
。 - (3 - 4) 根据投影,返回
r
中最小的元素。如果多个值与最小值等价,则返回最左侧的一个。
未定义行为
如果范围为空(由 ranges::distance(r)
确定),则行为未定义。
复杂度
- (1) 恰好一次比较。
- (3 - 4) 恰好
ranges::distance(r) - 1
次比较。
异常
(无)
可能的实现
min(1) 和 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;
备注
未定义行为
如果其中一个参数是临时变量并且该参数被返回,则通过引用捕获 std::ranges::min
的结果会产生悬空引用
int n = 1;
const int& r = std::ranges::min(n - 1, n + 1); // r is dangling
示例
Main.cpp
#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"