On Mon, 18 Aug 2025 at 10:14, Tomasz Kamiński wrote: > > 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.
Yes, I think that was just an oversight on my part. > > 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/minmax/constrained.cc: Likewise. > * testsuite/25_algorithms/minmax_element/constrained.cc: Likewise. > --- > Tested on x86_64-linux locally. > OK for trunk. > > libstdc++-v3/include/bits/ranges_algo.h | 118 +++++++++--------- > libstdc++-v3/include/bits/ranges_algobase.h | 4 +- > libstdc++-v3/include/bits/ranges_util.h | 29 ++--- > libstdc++-v3/include/bits/stl_algo.h | 8 +- > .../25_algorithms/max/constrained.cc | 4 +- > .../25_algorithms/min/constrained.cc | 4 +- > .../25_algorithms/minmax/constrained.cc | 16 ++- > .../minmax_element/constrained.cc | 16 ++- > 8 files changed, 108 insertions(+), 91 deletions(-) > > diff --git a/libstdc++-v3/include/bits/ranges_algo.h > b/libstdc++-v3/include/bits/ranges_algo.h > index 9f8945a7133..6e1e06cb2d0 100644 > --- a/libstdc++-v3/include/bits/ranges_algo.h > +++ b/libstdc++-v3/include/bits/ranges_algo.h > @@ -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, N.B. In older releases this would have needed the [[nodiscard]] to be placed after operator(), for compatibility with the Concepts TS (because otherwise the grammar says that the [[ is treated as a subscript operator for the requires-expression!) That's no longer an issue because the Concepts TS is not supported since GCC 15. OK for trunk, thanks.