std::min and std::maxSection: 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:Tmeets 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,Tmeets the Cpp17LessThanComparable requirements (Table 29).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 parameterTof the overloads in namespacestd.template<class T> constexpr T min(initializer_list<T> r);-?- Preconditions:
-?- Returns: The leftmost elementranges::distance(r) > 0.Tmeets the Cpp17CopyConstructible (Table 32) and Cpp17LessThanComparable (Table 29) requirements.xinrwherey < xisfalsefor all subsequent elementsy. -?- Complexity: Exactlyranges::distance(r) - 1comparisons. -?- 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.Tmeets the Cpp17CopyConstructible requirements (Table 32).xinrwherecomp(y, x)isfalsefor all subsequent elementsy. -?- Complexity: Exactlyranges::distance(r) - 1comparisons. -?- 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,Tmeets the Cpp17CopyConstructible requirements. For the first form,Tmeets the Cpp17LessThanComparable requirements (Table 29).xinrwherecomp(proj(y), proj(x))isfalsefor all subsequent elementsyThe 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) - 1comparisons and twice as many applications of the projection, if any.-8- Remarks: An invocation may explicitly specify an argument for the template parameterTof the overloads in namespacestd.template<class T> constexpr const T& max(const T& a, const T& b);-?- Preconditions:
-?- Returns:Tmeets 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,Tmeets the Cpp17LessThanComparable requirements (Table 29).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 parameterTof the overloads in namespacestd.template<class T> constexpr T max(initializer_list<T> r);-?- Preconditions:
-?- Returns: The leftmost elementranges::distance(r) > 0.Tmeets the Cpp17CopyConstructible (Table 32) and Cpp17LessThanComparable (Table 29) requirements.xinrwherex < yisfalsefor all subsequent elementsy. -?- Complexity: Exactlyranges::distance(r) - 1comparisons. -?- 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.Tmeets the Cpp17CopyConstructible requirements (Table 32).xinrwherecomp(x, y)isfalsefor all subsequent elementsy. -?- Complexity: Exactlyranges::distance(r) - 1comparisons. -?- 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,Tmeets the Cpp17CopyConstructible requirements. For the first form,Tmeets the Cpp17LessThanComparable requirements (Table 29).xinrwherecomp(proj(x), proj(y)isfalsefor all subsequent elementsyThe 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) - 1comparisons and twice as many applications of the projection, if any.-16- Remarks: An invocation may explicitly specify an argument for the template parameterTof the overloads in namespacestd.