std::min
and std::max
Section: 26.8.9 [alg.min.max] Status: New Submitter: Jan Schultke Opened: 2023-12-29 Last modified: 2024-08-02
Priority: 4
View other active issues in [alg.min.max].
View all other issues in [alg.min.max].
View all issues with New status.
Discussion:
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 26.8.9 [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?
[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.
Proposed resolution:
This wording is relative to N4971.
Modify 26.8.9 [alg.min.max] as indicated:
template<class T> constexpr const T& min(const T& a, const T& b);-?- Preconditions:
-?- Returns:T
meets the Cpp17LessThanComparable requirements (Table 29).b < a ? b : a
. -?- Remarks: An invocation may explicitly specify an argument for the template parameterT
.template<class T, class Compare> constexpr const T& min(const T& a, const T& b, Compare comp);-?- Returns:
-?- Remarks: An invocation may explicitly specify an argument for the template parametercomp(b, a) ? b : a
.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 = {});-2- Returns:
-1- Preconditions: For the first form,T
meets the Cpp17LessThanComparable requirements (Table 29).comp(proj(b), proj(a)) ? b : a
The 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 parameterT
of the overloads in namespacestd
.template<class T> constexpr T min(initializer_list<T> r);-?- Preconditions:
-?- Returns: The leftmost elementranges::distance(r) > 0
.T
meets the Cpp17CopyConstructible (Table 32) and Cpp17LessThanComparable (Table 29) requirements.x
inr
wherey < x
isfalse
for all subsequent elementsy
. -?- Complexity: Exactlyranges::distance(r) - 1
comparisons. -?- Remarks: An invocation may explicitly specify an argument for the template parameterT
.template<class T, class Compare> constexpr T min(initializer_list<T> r, Compare comp);-?- Preconditions:
-?- Returns: The leftmost elementranges::distance(r) > 0
.T
meets the Cpp17CopyConstructible requirements (Table 32).x
inr
wherecomp(y, x)
isfalse
for all subsequent elementsy
. -?- Complexity: Exactlyranges::distance(r) - 1
comparisons. -?- Remarks: An invocation may explicitly specify an argument for the template parameterT
.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:
-6- Returns: The leftmost elementranges::distance(r) > 0
.For the overloads in namespacestd
,T
meets the Cpp17CopyConstructible requirements. For the first form,T
meets the Cpp17LessThanComparable requirements (Table 29).x
inr
wherecomp(proj(y), proj(x))
isfalse
for all subsequent elementsy
The smallest value in the input range. Returns a copy of the leftmost element when several elements are equivalent to the smallest. -7- Complexity: Exactlyranges::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 parameterT
of the overloads in namespacestd
.template<class T> constexpr const T& max(const T& a, const T& b);-?- Preconditions:
-?- Returns:T
meets the Cpp17LessThanComparable requirements (Table 29).a < b ? b : a
. -?- Remarks: An invocation may explicitly specify an argument for the template parameterT
.template<class T, class Compare> constexpr const T& max(const T& a, const T& b, Compare comp);-?- Returns:
-?- Remarks: An invocation may explicitly specify an argument for the template parametercomp(a, b) ? b : a
.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 = {});-10- Returns:
-9- Preconditions: For the first form,T
meets the Cpp17LessThanComparable requirements (Table 29).comp(proj(a), proj(b)) ? b : a
The 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 parameterT
of the overloads in namespacestd
.template<class T> constexpr T max(initializer_list<T> r);-?- Preconditions:
-?- Returns: The leftmost elementranges::distance(r) > 0
.T
meets the Cpp17CopyConstructible (Table 32) and Cpp17LessThanComparable (Table 29) requirements.x
inr
wherex < y
isfalse
for all subsequent elementsy
. -?- Complexity: Exactlyranges::distance(r) - 1
comparisons. -?- Remarks: An invocation may explicitly specify an argument for the template parameterT
.template<class T, class Compare> constexpr T max(initializer_list<T> r, Compare comp);-?- Preconditions:
-?- Returns: The leftmost elementranges::distance(r) > 0
.T
meets the Cpp17CopyConstructible requirements (Table 32).x
inr
wherecomp(x, y)
isfalse
for all subsequent elementsy
. -?- Complexity: Exactlyranges::distance(r) - 1
comparisons. -?- Remarks: An invocation may explicitly specify an argument for the template parameterT
.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:
-14- Returns: The leftmost elementranges::distance(r) > 0
.For the overloads in namespacestd
,T
meets the Cpp17CopyConstructible requirements. For the first form,T
meets the Cpp17LessThanComparable requirements (Table 29).x
inr
wherecomp(proj(x), proj(y)
isfalse
for all subsequent elementsy
The largest value in the input range. Returns a copy of the leftmost element when several elements are equivalent to the largest. -15- Complexity: Exactlyranges::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 parameterT
of the overloads in namespacestd
.