Search code examples
c++c++11c++14undefined-behaviorstl-algorithm

Is calling std::min on an empty initializer list (and explicitly specifying the type) undefined behavior?


Calling std::min() with an empty initializer list usually does not compile (all the question can be stated in the same way for std::max()). This code:

#include <iostream>
#include <algorithm>

int main() {
   std::cout << std::min({}) << "\n";
   return 0;
}

With clang gives this error:

test.cpp:6:17: error: no matching function for call to 'min'
   std::cout << std::min({}) << "\n";
                ^~~~~~~~
algorithm:2599:1: note: 
      candidate template ignored: couldn't infer template argument '_Tp'
min(initializer_list<_Tp> __t)

I can see why this case would not be allowed, because it is difficult to agree on a sensible value to return in this case.

However, technically speaking the code does not compile only because the template parameter cannot be deduced. If I force the parameter the code compiles but I get a crash:

#include <iostream>
#include <algorithm>

int main() {

  std::cout << std::min<int>({}) << "\n";

  return 0;
}

$ clang++ -std=c++11 test.cpp -o test
$ ./test 
Segmentation fault: 11

It seems the crash arises because std::min() is implemented in terms of std::min_element(), and an empty initializer list results into the dereference of an invalid end() iterator.

So is this piece of code undefined behavior under C++11/C++14 ? Is std::min() stated to not compile when called without explicit template parameters? Is std::min() specified to be implemented in terms of std::min_element()?


Solution

  • Yes, it's UB. As per C++14 (n4140) 25.4.7/4:

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

    ...

    4 Requires: T is LessThanComparable and CopyConstructible and t.size() > 0.

    (Emphasis mine)

    The same wording is present in C++11 as well.