1308. Concerns about initializer_list overloads of min, max, and minmax

Section: 26.8.9 [alg.min.max] Status: NAD Submitter: Niels Dekker Opened: 2010-02-02 Last modified: 2017-09-07

Priority: Not Prioritized

View other active issues in [alg.min.max].

View all other issues in [alg.min.max].

View all issues with NAD status.

Discussion:

In San Francisco, June 2008, N2722 was adopted, replacing the variadic templates min, max, and minmax by overloads that have an initializer_list<T> parameter. The paper showed benchmark results wherein initializer_list versions of min appeared to outperform the corresponding variadic template. Unfortunately, in October 2009 a very serious error was detected in the benchmark. (c++std-lib-25210). In fact, an initializer_list<T> version of min often appears to perform worse than the corresponding variadic template, especially when T has an expensive copy constructor (c++std-lib-25253, http://www.xs4all.nl/~nd/dekkerware/issues/n2772_fix).

IMO, the biggest problem of the initializer_list overloads is that they pass and return T objects by value. Which has the following consequences:

  1. They require that T is CopyConstructible. IMO that is too much of a constraint for a generic, general purpose function like std::min<T>.
  2. They potentially throw an exception, even if T's less-than-operator throws nothing. (And of course, less-than typically throws nothing.)
  3. They are inconsistent with C++03 std::min and std::max. Consider the subtle difference between const T& c1 = min(a,b); and const T& c2 = min({a,b}); (c++std-lib-25265)
  4. They do not conveniently support use cases that need to have a reference to the minimum or maximum object itself, rather than just a copy.
  5. They potentially perform badly: possibly O(n), when the arguments themselves have a size of n.

In the future, this problem might be solvable by using an initializer_list of const references, instead:

const T& min(initializer_list<const T&>);
const T& max(initializer_list<const T&>);
pair<const T&, const T&> minmax(initializer_list<const T&>);

It is unlikely that C++0x will support initializer_list<const T&>, but technically it seems possible to add such a language feature after C++0x (c++std-core-15428).

Variadic templates of min, max, and minmax, as proposed by N2551 (Sylvain Pion), do have some other advantages over initializer_list overloads:

  1. It is likely that those variadic templates can be declared constexpr, now that CWG issue #991 is in drafting status.
  2. They provide complete compile-time protection against accidentally passing zero arguments.

Unfortunately, the variadic templates of min, max, and minmax may still need further improvement, before having them in the Standard Library. Especially the optional Compare parameter appears to be a concern. So for this moment I recommend to keep both versions out of C++0x, and postpone further discussion until after C++0x.

[ 2010 Pittsburgh: Discussed and the LWG still prefers the initializer list solution of N2772. ]

Rationale:

We prefer the solution of N2772 which will be reapplied.

Proposed resolution:

Remove both variadic templates and initializer_list overloads of min, max, and minmax from the synopsis in 26.1 [algorithms.general] and from 26.8.9 [alg.min.max].

[ Note: This proposed resolution will resolve LWG 915 as NAD. ]