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-08-02.23:14:28

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: 2024-08-15.00:00:00

[ 2024-08-02; Reflector poll ]

Set priority to 4 after reflector poll. Suggestions for NAD. "The result can be determined in any way that is allowed by the constaints the function imposes on its arguments. Since the arguments must be Cpp17LessThanComparable, obviously it has to use a less-than operation, because it can't assume any other operation is possible." Some of the submitter's questions could be addressed with an editorial change.

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-08-02 23:14:28adminsetmessages: + msg14298
2024-01-13 16:59:47adminsetmessages: + msg13912
2023-12-29 00:00:00admincreate