libstdc++: Add nodiscard attribute for ranges algorithm [PR121476]

This patch adds the [[nodiscard]] attribute to the operator() of ranges
algorithm function objects if their std counterpart has it.

Furthermore, we [[nodiscard]] the operator() of the following ranges
algorithms that lack a std counterpart:
* find_last, find_last_if, find_last_if_not (to match other find
  algorithms)
* contains, contains_subrange (to match find/any_of and search)

Finally, [[nodiscard]] is added to std::min and std::max overloads
that accept std::initializer_list. This appears to be an oversight,
as std::minmax is already marked, and other min overloads are as well.
The same applies to corresponding operator() overloads of ranges::min and
ranges::max.

	PR libstdc++/121476

libstdc++-v3/ChangeLog:

	* include/bits/ranges_algo.h (__all_of_fn::operator()):
	(__any_of_fn::operator(), __none_of_fn::operator())
	(__find_first_of_fn::operator(), __count_fn::operator())
	(__find_end_fn::operator(), __remove_if_fn::operator())
	(__remove_fn::operator(), __unique_fn::operator())
	(__is_sorted_until_fn::operator(), __is_sorted_fn::operator())
	(__lower_bound_fn::operator(), __upper_bound_fn::operator())
	(__equal_range_fn::operator(), __binary_search_fn::operator())
	(__is_partitioned_fn::operator(), __partition_point_fn::operator())
	(__minmax_fn::operator(), __min_element_fn::operator())
	(__includes_fn::operator(), __max_fn::operator())
	(__lexicographical_compare_fn::operator(), __clamp__fn::operator())
	(__find_last_fn::operator(), __find_last_if_fn::operator())
	(__find_last_if_not_fn::operator()): Add [[nodiscard]] attribute.
	* include/bits/ranges_algobase.h (__equal_fn::operator()):
	Add [[nodiscard]] attribute.
	* include/bits/ranges_util.h (__find_fn::operator())
	(__find_if_fn::operator(), __find_if_not_fn::operator())
	(__mismatch_fn::operator(), __search_fn::operator())
	(__min_fn::operator(), __adjacent_find_fn::operator()):
	Add [[nodiscard]] attribute.
	* include/bits/stl_algo.h (std::min(initializer_list<T>))
	(std::min(initializer_list<T>, _Compare))
	(std::max(initializer_list<T>))
	(std::mmax(initializer_list<T>, _Compare)): Add _GLIBCXX_NODISCARD.
	* testsuite/25_algorithms/min/constrained.cc: Silence nodiscard
	warning.
	* testsuite/25_algorithms/max/constrained.cc: Likewise.
	* testsuite/25_algorithms/minmax/constrained.cc: Likewise.
	* testsuite/25_algorithms/minmax_element/constrained.cc: Likewise.
This commit is contained in:
Tomasz Kamiński
2025-08-14 16:54:16 +02:00
parent 4a56ba8c8e
commit ea8ef43971
8 changed files with 108 additions and 91 deletions

View File

@@ -109,7 +109,7 @@ namespace ranges
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
typename _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
constexpr bool
[[nodiscard]] constexpr bool
operator()(_Iter __first, _Sent __last,
_Pred __pred, _Proj __proj = {}) const
{
@@ -122,7 +122,7 @@ namespace ranges
template<input_range _Range, typename _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
_Pred>
constexpr bool
[[nodiscard]] constexpr bool
operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -137,7 +137,7 @@ namespace ranges
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
typename _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
constexpr bool
[[nodiscard]] constexpr bool
operator()(_Iter __first, _Sent __last,
_Pred __pred, _Proj __proj = {}) const
{
@@ -150,7 +150,7 @@ namespace ranges
template<input_range _Range, typename _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
_Pred>
constexpr bool
[[nodiscard]] constexpr bool
operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -165,7 +165,7 @@ namespace ranges
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
typename _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
constexpr bool
[[nodiscard]] constexpr bool
operator()(_Iter __first, _Sent __last,
_Pred __pred, _Proj __proj = {}) const
{
@@ -178,7 +178,7 @@ namespace ranges
template<input_range _Range, typename _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
_Pred>
constexpr bool
[[nodiscard]] constexpr bool
operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -279,7 +279,7 @@ namespace ranges
typename _Pred = ranges::equal_to,
typename _Proj1 = identity, typename _Proj2 = identity>
requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
constexpr _Iter1
[[nodiscard]] constexpr _Iter1
operator()(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2, _Pred __pred = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
@@ -298,7 +298,7 @@ namespace ranges
typename _Proj1 = identity, typename _Proj2 = identity>
requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>,
_Pred, _Proj1, _Proj2>
constexpr borrowed_iterator_t<_Range1>
[[nodiscard]] constexpr borrowed_iterator_t<_Range1>
operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
{
@@ -319,7 +319,7 @@ namespace ranges
requires indirect_binary_predicate<ranges::equal_to,
projected<_Iter, _Proj>,
const _Tp*>
constexpr iter_difference_t<_Iter>
[[nodiscard]] constexpr iter_difference_t<_Iter>
operator()(_Iter __first, _Sent __last,
const _Tp& __value, _Proj __proj = {}) const
{
@@ -336,7 +336,7 @@ namespace ranges
requires indirect_binary_predicate<ranges::equal_to,
projected<iterator_t<_Range>, _Proj>,
const _Tp*>
constexpr range_difference_t<_Range>
[[nodiscard]] constexpr range_difference_t<_Range>
operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -726,7 +726,7 @@ namespace ranges
typename _Pred = ranges::equal_to,
typename _Proj1 = identity, typename _Proj2 = identity>
requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
constexpr subrange<_Iter1>
[[nodiscard]] constexpr subrange<_Iter1>
operator()(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2, _Pred __pred = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
@@ -783,7 +783,7 @@ namespace ranges
typename _Proj1 = identity, typename _Proj2 = identity>
requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>,
_Pred, _Proj1, _Proj2>
constexpr borrowed_subrange_t<_Range1>
[[nodiscard]] constexpr borrowed_subrange_t<_Range1>
operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
{
@@ -806,7 +806,7 @@ namespace ranges
indirect_equivalence_relation<projected<_Iter1, _Proj1>,
projected<_Iter2, _Proj2>> _Pred
= ranges::equal_to>
constexpr bool
[[nodiscard]] constexpr bool
operator()(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2, _Pred __pred = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
@@ -875,7 +875,7 @@ namespace ranges
indirect_equivalence_relation<
projected<iterator_t<_Range1>, _Proj1>,
projected<iterator_t<_Range2>, _Proj2>> _Pred = ranges::equal_to>
constexpr bool
[[nodiscard]] constexpr bool
operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
{
@@ -1281,7 +1281,7 @@ namespace ranges
template<permutable _Iter, sentinel_for<_Iter> _Sent,
typename _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
constexpr subrange<_Iter>
[[nodiscard]] constexpr subrange<_Iter>
operator()(_Iter __first, _Sent __last,
_Pred __pred, _Proj __proj = {}) const
{
@@ -1305,7 +1305,7 @@ namespace ranges
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
_Pred>
requires permutable<iterator_t<_Range>>
constexpr borrowed_subrange_t<_Range>
[[nodiscard]] constexpr borrowed_subrange_t<_Range>
operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -1323,7 +1323,7 @@ namespace ranges
requires indirect_binary_predicate<ranges::equal_to,
projected<_Iter, _Proj>,
const _Tp*>
constexpr subrange<_Iter>
[[nodiscard]] constexpr subrange<_Iter>
operator()(_Iter __first, _Sent __last,
const _Tp& __value, _Proj __proj = {}) const
{
@@ -1341,7 +1341,7 @@ namespace ranges
&& indirect_binary_predicate<ranges::equal_to,
projected<iterator_t<_Range>, _Proj>,
const _Tp*>
constexpr borrowed_subrange_t<_Range>
[[nodiscard]] constexpr borrowed_subrange_t<_Range>
operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -1440,7 +1440,7 @@ namespace ranges
typename _Proj = identity,
indirect_equivalence_relation<
projected<_Iter, _Proj>> _Comp = ranges::equal_to>
constexpr subrange<_Iter>
[[nodiscard]] constexpr subrange<_Iter>
operator()(_Iter __first, _Sent __last,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -1462,7 +1462,7 @@ namespace ranges
indirect_equivalence_relation<
projected<iterator_t<_Range>, _Proj>> _Comp = ranges::equal_to>
requires permutable<iterator_t<_Range>>
constexpr borrowed_subrange_t<_Range>
[[nodiscard]] constexpr borrowed_subrange_t<_Range>
operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -2849,7 +2849,7 @@ namespace ranges
typename _Proj = identity,
indirect_strict_weak_order<projected<_Iter, _Proj>>
_Comp = ranges::less>
constexpr _Iter
[[nodiscard]] constexpr _Iter
operator()(_Iter __first, _Sent __last,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -2868,7 +2868,7 @@ namespace ranges
template<forward_range _Range, typename _Proj = identity,
indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
_Comp = ranges::less>
constexpr borrowed_iterator_t<_Range>
[[nodiscard]] constexpr borrowed_iterator_t<_Range>
operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -2884,7 +2884,7 @@ namespace ranges
typename _Proj = identity,
indirect_strict_weak_order<projected<_Iter, _Proj>>
_Comp = ranges::less>
constexpr bool
[[nodiscard]] constexpr bool
operator()(_Iter __first, _Sent __last,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -2903,7 +2903,7 @@ namespace ranges
template<forward_range _Range, typename _Proj = identity,
indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
_Comp = ranges::less>
constexpr bool
[[nodiscard]] constexpr bool
operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -2987,7 +2987,7 @@ namespace ranges
typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj),
indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>>
_Comp = ranges::less>
constexpr _Iter
[[nodiscard]] constexpr _Iter
operator()(_Iter __first, _Sent __last,
const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const
{
@@ -3017,7 +3017,7 @@ namespace ranges
indirect_strict_weak_order<const _Tp*,
projected<iterator_t<_Range>, _Proj>>
_Comp = ranges::less>
constexpr borrowed_iterator_t<_Range>
[[nodiscard]] constexpr borrowed_iterator_t<_Range>
operator()(_Range&& __r,
const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const
{
@@ -3035,7 +3035,7 @@ namespace ranges
typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj),
indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>>
_Comp = ranges::less>
constexpr _Iter
[[nodiscard]] constexpr _Iter
operator()(_Iter __first, _Sent __last,
const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const
{
@@ -3065,7 +3065,7 @@ namespace ranges
indirect_strict_weak_order<const _Tp*,
projected<iterator_t<_Range>, _Proj>>
_Comp = ranges::less>
constexpr borrowed_iterator_t<_Range>
[[nodiscard]] constexpr borrowed_iterator_t<_Range>
operator()(_Range&& __r,
const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const
{
@@ -3083,7 +3083,7 @@ namespace ranges
typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj),
indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>>
_Comp = ranges::less>
constexpr subrange<_Iter>
[[nodiscard]] constexpr subrange<_Iter>
operator()(_Iter __first, _Sent __last,
const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const
{
@@ -3128,7 +3128,7 @@ namespace ranges
indirect_strict_weak_order<const _Tp*,
projected<iterator_t<_Range>, _Proj>>
_Comp = ranges::less>
constexpr borrowed_subrange_t<_Range>
[[nodiscard]] constexpr borrowed_subrange_t<_Range>
operator()(_Range&& __r, const _Tp& __value,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -3146,7 +3146,7 @@ namespace ranges
typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj),
indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>>
_Comp = ranges::less>
constexpr bool
[[nodiscard]] constexpr bool
operator()(_Iter __first, _Sent __last,
const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const
{
@@ -3164,7 +3164,7 @@ namespace ranges
indirect_strict_weak_order<const _Tp*,
projected<iterator_t<_Range>, _Proj>>
_Comp = ranges::less>
constexpr bool
[[nodiscard]] constexpr bool
operator()(_Range&& __r, const _Tp& __value, _Comp __comp = {},
_Proj __proj = {}) const
{
@@ -3180,7 +3180,7 @@ namespace ranges
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
typename _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
constexpr bool
[[nodiscard]] constexpr bool
operator()(_Iter __first, _Sent __last,
_Pred __pred, _Proj __proj = {}) const
{
@@ -3196,7 +3196,7 @@ namespace ranges
template<input_range _Range, typename _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
_Pred>
constexpr bool
[[nodiscard]] constexpr bool
operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -3488,7 +3488,7 @@ namespace ranges
template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
typename _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
constexpr _Iter
[[nodiscard]] constexpr _Iter
operator()(_Iter __first, _Sent __last,
_Pred __pred, _Proj __proj = {}) const
{
@@ -3514,7 +3514,7 @@ namespace ranges
template<forward_range _Range, typename _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
_Pred>
constexpr borrowed_iterator_t<_Range>
[[nodiscard]] constexpr borrowed_iterator_t<_Range>
operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -3875,7 +3875,7 @@ namespace ranges
indirect_strict_weak_order<projected<_Iter1, _Proj1>,
projected<_Iter2, _Proj2>>
_Comp = ranges::less>
constexpr bool
[[nodiscard]] constexpr bool
operator()(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2,
_Comp __comp = {},
@@ -3904,7 +3904,7 @@ namespace ranges
indirect_strict_weak_order<projected<iterator_t<_Range1>, _Proj1>,
projected<iterator_t<_Range2>, _Proj2>>
_Comp = ranges::less>
constexpr bool
[[nodiscard]] constexpr bool
operator()(_Range1&& __r1, _Range2&& __r2, _Comp __comp = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
{
@@ -4175,7 +4175,7 @@ namespace ranges
template<typename _Tp, typename _Proj = identity,
indirect_strict_weak_order<projected<const _Tp*, _Proj>>
_Comp = ranges::less>
constexpr const _Tp&
[[nodiscard]] constexpr const _Tp&
operator()(const _Tp& __a, const _Tp& __b,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -4192,7 +4192,7 @@ namespace ranges
_Comp = ranges::less>
requires indirectly_copyable_storable<iterator_t<_Range>,
range_value_t<_Range>*>
constexpr range_value_t<_Range>
[[nodiscard]] constexpr range_value_t<_Range>
operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
{
auto __first = ranges::begin(__r);
@@ -4213,7 +4213,7 @@ namespace ranges
template<copyable _Tp, typename _Proj = identity,
indirect_strict_weak_order<projected<const _Tp*, _Proj>>
_Comp = ranges::less>
constexpr _Tp
[[nodiscard]] constexpr _Tp
operator()(initializer_list<_Tp> __r,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -4229,7 +4229,7 @@ namespace ranges
template<typename _Tp, typename _Proj = identity,
indirect_strict_weak_order<projected<const _Tp*, _Proj>> _Comp
= ranges::less>
constexpr const _Tp&
[[nodiscard]] constexpr const _Tp&
operator()(const _Tp& __val, const _Tp& __lo, const _Tp& __hi,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -4279,7 +4279,7 @@ namespace ranges
template<typename _Tp, typename _Proj = identity,
indirect_strict_weak_order<projected<const _Tp*, _Proj>>
_Comp = ranges::less>
constexpr minmax_result<const _Tp&>
[[nodiscard]] constexpr minmax_result<const _Tp&>
operator()(const _Tp& __a, const _Tp& __b,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -4295,7 +4295,7 @@ namespace ranges
indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
_Comp = ranges::less>
requires indirectly_copyable_storable<iterator_t<_Range>, range_value_t<_Range>*>
constexpr minmax_result<range_value_t<_Range>>
[[nodiscard]] constexpr minmax_result<range_value_t<_Range>>
operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
{
auto __first = ranges::begin(__r);
@@ -4354,7 +4354,7 @@ namespace ranges
template<copyable _Tp, typename _Proj = identity,
indirect_strict_weak_order<projected<const _Tp*, _Proj>>
_Comp = ranges::less>
constexpr minmax_result<_Tp>
[[nodiscard]] constexpr minmax_result<_Tp>
operator()(initializer_list<_Tp> __r,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -4371,7 +4371,7 @@ namespace ranges
typename _Proj = identity,
indirect_strict_weak_order<projected<_Iter, _Proj>>
_Comp = ranges::less>
constexpr _Iter
[[nodiscard]] constexpr _Iter
operator()(_Iter __first, _Sent __last,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -4392,7 +4392,7 @@ namespace ranges
template<forward_range _Range, typename _Proj = identity,
indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
_Comp = ranges::less>
constexpr borrowed_iterator_t<_Range>
[[nodiscard]] constexpr borrowed_iterator_t<_Range>
operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -4408,7 +4408,7 @@ namespace ranges
typename _Proj = identity,
indirect_strict_weak_order<projected<_Iter, _Proj>>
_Comp = ranges::less>
constexpr _Iter
[[nodiscard]] constexpr _Iter
operator()(_Iter __first, _Sent __last,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -4429,7 +4429,7 @@ namespace ranges
template<forward_range _Range, typename _Proj = identity,
indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
_Comp = ranges::less>
constexpr borrowed_iterator_t<_Range>
[[nodiscard]] constexpr borrowed_iterator_t<_Range>
operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -4448,7 +4448,7 @@ namespace ranges
typename _Proj = identity,
indirect_strict_weak_order<projected<_Iter, _Proj>>
_Comp = ranges::less>
constexpr minmax_element_result<_Iter>
[[nodiscard]] constexpr minmax_element_result<_Iter>
operator()(_Iter __first, _Sent __last,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -4503,7 +4503,7 @@ namespace ranges
template<forward_range _Range, typename _Proj = identity,
indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
_Comp = ranges::less>
constexpr minmax_element_result<borrowed_iterator_t<_Range>>
[[nodiscard]] constexpr minmax_element_result<borrowed_iterator_t<_Range>>
operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -4521,7 +4521,7 @@ namespace ranges
indirect_strict_weak_order<projected<_Iter1, _Proj1>,
projected<_Iter2, _Proj2>>
_Comp = ranges::less>
constexpr bool
[[nodiscard]] constexpr bool
operator()(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2,
_Comp __comp = {},
@@ -4607,7 +4607,7 @@ namespace ranges
indirect_strict_weak_order<projected<iterator_t<_Range1>, _Proj1>,
projected<iterator_t<_Range2>, _Proj2>>
_Comp = ranges::less>
constexpr bool
[[nodiscard]] constexpr bool
operator()(_Range1&& __r1, _Range2&& __r2, _Comp __comp = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
{
@@ -4836,7 +4836,7 @@ namespace ranges
typename _Proj = identity,
typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj)>
requires indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>, const _Tp*>
constexpr subrange<_Iter>
[[nodiscard]] constexpr subrange<_Iter>
operator()(_Iter __first, _Sent __last, const _Tp& __value, _Proj __proj = {}) const
{
if constexpr (same_as<_Iter, _Sent> && bidirectional_iterator<_Iter>)
@@ -4869,7 +4869,7 @@ namespace ranges
typename _Tp
_GLIBCXX26_RANGE_ALGO_DEF_VAL_T(iterator_t<_Range>, _Proj)>
requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _Tp*>
constexpr borrowed_subrange_t<_Range>
[[nodiscard]] constexpr borrowed_subrange_t<_Range>
operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const
{ return (*this)(ranges::begin(__r), ranges::end(__r), __value, std::move(__proj)); }
};
@@ -4880,7 +4880,7 @@ namespace ranges
{
template<forward_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
constexpr subrange<_Iter>
[[nodiscard]] constexpr subrange<_Iter>
operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const
{
if constexpr (same_as<_Iter, _Sent> && bidirectional_iterator<_Iter>)
@@ -4911,7 +4911,7 @@ namespace ranges
template<forward_range _Range, typename _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
constexpr borrowed_subrange_t<_Range>
[[nodiscard]] constexpr borrowed_subrange_t<_Range>
operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
{ return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__pred), std::move(__proj)); }
};
@@ -4922,7 +4922,7 @@ namespace ranges
{
template<forward_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
constexpr subrange<_Iter>
[[nodiscard]] constexpr subrange<_Iter>
operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const
{
if constexpr (same_as<_Iter, _Sent> && bidirectional_iterator<_Iter>)
@@ -4953,7 +4953,7 @@ namespace ranges
template<forward_range _Range, typename _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
constexpr borrowed_subrange_t<_Range>
[[nodiscard]] constexpr borrowed_subrange_t<_Range>
operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
{ return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__pred), std::move(__proj)); }
};

View File

@@ -101,7 +101,7 @@ namespace ranges
typename _Pred = ranges::equal_to,
typename _Proj1 = identity, typename _Proj2 = identity>
requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
constexpr bool
[[nodiscard]] constexpr bool
operator()(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2, _Pred __pred = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
@@ -168,7 +168,7 @@ namespace ranges
typename _Proj1 = identity, typename _Proj2 = identity>
requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>,
_Pred, _Proj1, _Proj2>
constexpr bool
[[nodiscard]] constexpr bool
operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
{

View File

@@ -501,7 +501,7 @@ namespace ranges
typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj)>
requires indirect_binary_predicate<ranges::equal_to,
projected<_Iter, _Proj>, const _Tp*>
constexpr _Iter
[[nodiscard]] constexpr _Iter
operator()(_Iter __first, _Sent __last,
const _Tp& __value, _Proj __proj = {}) const
{
@@ -537,7 +537,7 @@ namespace ranges
requires indirect_binary_predicate<ranges::equal_to,
projected<iterator_t<_Range>, _Proj>,
const _Tp*>
constexpr borrowed_iterator_t<_Range>
[[nodiscard]] constexpr borrowed_iterator_t<_Range>
operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -552,7 +552,7 @@ namespace ranges
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
typename _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
constexpr _Iter
[[nodiscard]] constexpr _Iter
operator()(_Iter __first, _Sent __last,
_Pred __pred, _Proj __proj = {}) const
{
@@ -565,7 +565,7 @@ namespace ranges
template<input_range _Range, typename _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
_Pred>
constexpr borrowed_iterator_t<_Range>
[[nodiscard]] constexpr borrowed_iterator_t<_Range>
operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -580,7 +580,7 @@ namespace ranges
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
typename _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
constexpr _Iter
[[nodiscard]] constexpr _Iter
operator()(_Iter __first, _Sent __last,
_Pred __pred, _Proj __proj = {}) const
{
@@ -593,7 +593,7 @@ namespace ranges
template<input_range _Range, typename _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
_Pred>
constexpr borrowed_iterator_t<_Range>
[[nodiscard]] constexpr borrowed_iterator_t<_Range>
operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
@@ -634,7 +634,7 @@ namespace ranges
typename _Pred = ranges::equal_to,
typename _Proj1 = identity, typename _Proj2 = identity>
requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
constexpr mismatch_result<_Iter1, _Iter2>
[[nodiscard]] constexpr mismatch_result<_Iter1, _Iter2>
operator()(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2, _Pred __pred = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
@@ -655,6 +655,7 @@ namespace ranges
typename _Proj1 = identity, typename _Proj2 = identity>
requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>,
_Pred, _Proj1, _Proj2>
[[nodiscard]]
constexpr mismatch_result<iterator_t<_Range1>, iterator_t<_Range2>>
operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
@@ -675,7 +676,7 @@ namespace ranges
typename _Pred = ranges::equal_to,
typename _Proj1 = identity, typename _Proj2 = identity>
requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
constexpr subrange<_Iter1>
[[nodiscard]] constexpr subrange<_Iter1>
operator()(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2, _Pred __pred = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
@@ -719,7 +720,7 @@ namespace ranges
typename _Proj1 = identity, typename _Proj2 = identity>
requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>,
_Pred, _Proj1, _Proj2>
constexpr borrowed_subrange_t<_Range1>
[[nodiscard]] constexpr borrowed_subrange_t<_Range1>
operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
{
@@ -737,7 +738,7 @@ namespace ranges
template<typename _Tp, typename _Proj = identity,
indirect_strict_weak_order<projected<const _Tp*, _Proj>>
_Comp = ranges::less>
constexpr const _Tp&
[[nodiscard]] constexpr const _Tp&
operator()(const _Tp& __a, const _Tp& __b,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -754,7 +755,7 @@ namespace ranges
_Comp = ranges::less>
requires indirectly_copyable_storable<iterator_t<_Range>,
range_value_t<_Range>*>
constexpr range_value_t<_Range>
[[nodiscard]] constexpr range_value_t<_Range>
operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
{
auto __first = ranges::begin(__r);
@@ -775,7 +776,7 @@ namespace ranges
template<copyable _Tp, typename _Proj = identity,
indirect_strict_weak_order<projected<const _Tp*, _Proj>>
_Comp = ranges::less>
constexpr _Tp
[[nodiscard]] constexpr _Tp
operator()(initializer_list<_Tp> __r,
_Comp __comp = {}, _Proj __proj = {}) const
{
@@ -793,7 +794,7 @@ namespace ranges
indirect_binary_predicate<projected<_Iter, _Proj>,
projected<_Iter, _Proj>> _Pred
= ranges::equal_to>
constexpr _Iter
[[nodiscard]] constexpr _Iter
operator()(_Iter __first, _Sent __last,
_Pred __pred = {}, _Proj __proj = {}) const
{
@@ -814,7 +815,7 @@ namespace ranges
indirect_binary_predicate<
projected<iterator_t<_Range>, _Proj>,
projected<iterator_t<_Range>, _Proj>> _Pred = ranges::equal_to>
constexpr borrowed_iterator_t<_Range>
[[nodiscard]] constexpr borrowed_iterator_t<_Range>
operator()(_Range&& __r, _Pred __pred = {}, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),

View File

@@ -5759,7 +5759,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
#if __cplusplus >= 201103L
// N2722 + DR 915.
template<typename _Tp>
_GLIBCXX14_CONSTEXPR
_GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR
inline _Tp
min(initializer_list<_Tp> __l)
{
@@ -5769,7 +5769,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
}
template<typename _Tp, typename _Compare>
_GLIBCXX14_CONSTEXPR
_GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR
inline _Tp
min(initializer_list<_Tp> __l, _Compare __comp)
{
@@ -5779,7 +5779,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
}
template<typename _Tp>
_GLIBCXX14_CONSTEXPR
_GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR
inline _Tp
max(initializer_list<_Tp> __l)
{
@@ -5789,7 +5789,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
}
template<typename _Tp, typename _Compare>
_GLIBCXX14_CONSTEXPR
_GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR
inline _Tp
max(initializer_list<_Tp> __l, _Compare __comp)
{

View File

@@ -87,12 +87,12 @@ test04()
int m;
};
A r[5] = {5, 4, 3, 2, 1};
ranges::max(r, ranges::less{}, &A::m);
(void)ranges::max(r, ranges::less{}, &A::m);
VERIFY( copies == 1 );
VERIFY( moves == 0 );
copies = moves = 0;
A s[5] = {1, 2, 3, 4, 5};
ranges::max(s, ranges::less{}, &A::m);
(void)ranges::max(s, ranges::less{}, &A::m);
VERIFY( copies == 5 );
VERIFY( moves == 0 );
}

View File

@@ -87,12 +87,12 @@ test04()
int m;
};
A r[5] = {5, 4, 3, 2, 1};
ranges::min(r, ranges::less{}, &A::m);
(void)ranges::min(r, ranges::less{}, &A::m);
VERIFY( copies == 5 );
VERIFY( moves == 0 );
copies = moves = 0;
A s[5] = {1, 2, 3, 4, 5};
ranges::min(s, ranges::less{}, &A::m);
(void)ranges::min(s, ranges::less{}, &A::m);
VERIFY( copies == 1 );
VERIFY( moves == 0 );
}

View File

@@ -99,20 +99,28 @@ test04()
struct counted_less
{ bool operator()(int a, int b) { ++counter; return a < b; } };
ranges::minmax({1,2}, counted_less{});
auto p = ranges::minmax({1,2}, counted_less{});
VERIFY( counter == 1 );
VERIFY( p.min = 1 );
VERIFY( p.max = 2 );
counter = 0;
ranges::minmax({1,2,3}, counted_less{});
p = ranges::minmax({1,2,3}, counted_less{});
VERIFY( counter == 3 );
VERIFY( p.min = 1 );
VERIFY( p.max = 3 );
counter = 0;
ranges::minmax({1,2,3,4,5,6,7,8,9,10}, counted_less{});
p = ranges::minmax({1,2,3,4,5,6,7,8,9,10}, counted_less{});
VERIFY( counter <= 15 );
VERIFY( p.min = 1 );
VERIFY( p.max = 10 );
counter = 0;
ranges::minmax({10,9,8,7,6,5,4,3,2,1}, counted_less{});
p = ranges::minmax({10,9,8,7,6,5,4,3,2,1}, counted_less{});
VERIFY( counter <= 15 );
VERIFY( p.min = 1 );
VERIFY( p.max = 10 );
}
void

View File

@@ -70,21 +70,29 @@ test02()
{ bool operator()(int a, int b) { ++counter; return a < b; } };
int x[] = {1,2,3,4,5,6,7,8,9,10};
ranges::minmax_element(x, x+2, counted_less{});
auto p = ranges::minmax_element(x, x+2, counted_less{});
VERIFY( counter == 1 );
VERIFY( p.min == x+0 );
VERIFY( p.max == x+1 );
counter = 0;
ranges::minmax_element(x, x+3, counted_less{});
p = ranges::minmax_element(x, x+3, counted_less{});
VERIFY( counter == 3 );
VERIFY( p.min == x+0 );
VERIFY( p.max == x+2 );
counter = 0;
ranges::minmax_element(x, counted_less{});
p = ranges::minmax_element(x, counted_less{});
VERIFY( counter <= 15 );
VERIFY( p.min == x+0 );
VERIFY( p.max == x+9 );
ranges::reverse(x);
counter = 0;
ranges::minmax_element(x, counted_less{});
p = ranges::minmax_element(x, counted_less{});
VERIFY( counter <= 15 );
VERIFY( p.min == x+9 );
VERIFY( p.max == x+0 );
}
int