Title
Clarify specification of std::min and std::max
Status
new
Section
[alg.min.max]
Submitter
Jan Schultke

Created on 2023-12-29.00:00:00 last changed 3 months ago

Messages

Date: 2024-01-13.16:59:47

Proposed resolution:

This wording is relative to N4971.

  1. Modify [alg.min.max] as indicated:

    template<class T>
      constexpr const T& min(const T& a, const T& b);
    

    -?- Preconditions: T meets the Cpp17LessThanComparable requirements (Table 29).

    -?- Returns: b < a ? b : a.

    -?- Remarks: An invocation may explicitly specify an argument for the template parameter T.

    template<class T, class Compare>
      constexpr const T& min(const T& a, const T& b, Compare comp);
    

    -?- Returns: comp(b, a) ? b : a.

    -?- Remarks: An invocation may explicitly specify an argument for the template parameter T.

    template<class T, class Proj = identity,
             indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less>
    constexpr const T& ranges::min(const T& a, const T& b, Comp comp = {}, Proj proj = {});
    

    -1- Preconditions: For the first form, T meets the Cpp17LessThanComparable requirements (Table 29).

    -2- Returns: comp(proj(b), proj(a)) ? b : aThe smaller value. Returns the first argument when the arguments are equivalent.

    -3- Complexity: Exactly one comparison and two applications of the projection, if any.

    -4- Remarks: An invocation may explicitly specify an argument for the template parameter T of the overloads in namespace std.

    template<class T>
      constexpr T min(initializer_list<T> r);
    

    -?- Preconditions: ranges::distance(r) > 0. T meets the Cpp17CopyConstructible (Table 32) and Cpp17LessThanComparable (Table 29) requirements.

    -?- Returns: The leftmost element x in r where y < x is false for all subsequent elements y.

    -?- Complexity: Exactly ranges::distance(r) - 1 comparisons.

    -?- Remarks: An invocation may explicitly specify an argument for the template parameter T.

    template<class T, class Compare>
      constexpr T min(initializer_list<T> r, Compare comp);
    

    -?- Preconditions: ranges::distance(r) > 0. T meets the Cpp17CopyConstructible requirements (Table 32).

    -?- Returns: The leftmost element x in r where comp(y, x) is false for all subsequent elements y.

    -?- Complexity: Exactly ranges::distance(r) - 1 comparisons.

    -?- Remarks: An invocation may explicitly specify an argument for the template parameter T.

    template<copyable T, class Proj = identity,
             indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less>
      constexpr T ranges::min(initializer_list<T> r, Comp comp = {}, Proj proj = {});
    template<input_range R, class Proj = identity,
             indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less>
      requires indirectly_copyable_storable<iterator_t<R>, range_value_t<R>*>
      constexpr range_value_t<R>
        ranges::min(R&& r, Comp comp = {}, Proj proj = {});
    

    -5- Preconditions: ranges::distance(r) > 0. For the overloads in namespace std, T meets the Cpp17CopyConstructible requirements. For the first form, T meets the Cpp17LessThanComparable requirements (Table 29).

    -6- Returns: The leftmost element x in r where comp(proj(y), proj(x)) is false for all subsequent elements yThe smallest value in the input range. Returns a copy of the leftmost element when several elements are equivalent to the smallest.

    -7- Complexity: Exactly ranges::distance(r) - 1 comparisons and twice as many applications of the projection, if any.

    -8- Remarks: An invocation may explicitly specify an argument for the template parameter T of the overloads in namespace std.

    template<class T>
      constexpr const T& max(const T& a, const T& b);
    

    -?- Preconditions: T meets the Cpp17LessThanComparable requirements (Table 29).

    -?- Returns: a < b ? b : a.

    -?- Remarks: An invocation may explicitly specify an argument for the template parameter T.

    template<class T, class Compare>
      constexpr const T& max(const T& a, const T& b, Compare comp);
    

    -?- Returns: comp(a, b) ? b : a.

    -?- Remarks: An invocation may explicitly specify an argument for the template parameter T.

    template<class T, class Proj = identity,
             indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less>
      constexpr const T& ranges::max(const T& a, const T& b, Comp comp = {}, Proj proj = {});
    

    -9- Preconditions: For the first form, T meets the Cpp17LessThanComparable requirements (Table 29).

    -10- Returns: comp(proj(a), proj(b)) ? b : aThe larger value. Returns the first argument when the arguments are equivalent.

    -11- Complexity: Exactly one comparison and two applications of the projection, if any.

    -12- Remarks: An invocation may explicitly specify an argument for the template parameter T of the overloads in namespace std.

    template<class T>
      constexpr T max(initializer_list<T> r);
    

    -?- Preconditions: ranges::distance(r) > 0. T meets the Cpp17CopyConstructible (Table 32) and Cpp17LessThanComparable (Table 29) requirements.

    -?- Returns: The leftmost element x in r where x < y is false for all subsequent elements y.

    -?- Complexity: Exactly ranges::distance(r) - 1 comparisons.

    -?- Remarks: An invocation may explicitly specify an argument for the template parameter T.

    template<class T, class Compare>
      constexpr T max(initializer_list<T> r, Compare comp);
    

    -?- Preconditions: ranges::distance(r) > 0. T meets the Cpp17CopyConstructible requirements (Table 32).

    -?- Returns: The leftmost element x in r where comp(x, y) is false for all subsequent elements y.

    -?- Complexity: Exactly ranges::distance(r) - 1 comparisons.

    -?- Remarks: An invocation may explicitly specify an argument for the template parameter T.

    template<copyable T, class Proj = identity,
             indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less>
      constexpr T ranges::max(initializer_list<T> r, Comp comp = {}, Proj proj = {});
    template<input_range R, class Proj = identity,
             indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less>
      requires indirectly_copyable_storable<iterator_t<R>, range_value_t<R>*>
      constexpr range_value_t<R>
        ranges::max(R&& r, Comp comp = {}, Proj proj = {});
    

    -13- Preconditions: ranges::distance(r) > 0. For the overloads in namespace std, T meets the Cpp17CopyConstructible requirements. For the first form, T meets the Cpp17LessThanComparable requirements (Table 29).

    -14- Returns: The leftmost element x in r where comp(proj(x), proj(y) is false for all subsequent elements yThe largest value in the input range. Returns a copy of the leftmost element when several elements are equivalent to the largest.

    -15- Complexity: Exactly ranges::distance(r) - 1 comparisons and twice as many applications of the projection, if any.

    -16- Remarks: An invocation may explicitly specify an argument for the template parameter T of the overloads in namespace std.

Date: 2023-12-29.00:00:00

All standard libraries effectively use the same implementation for std::min(a, b), namely something along the lines of

return __b < __a ? __b : __a;

However, the wording in [alg.min.max] is not so clear:

Returns: The smaller value. Returns the first argument when the arguments are equivalent.

This leaves a few questions open:

  • How is the smaller value determined? Must it be through the less-than operator?

  • For std::max, can the "larger" value be determined through the greater-than operator or must it be through less-than?

History
Date User Action Args
2024-01-13 16:59:47adminsetmessages: + msg13912
2023-12-29 00:00:00admincreate