Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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()?

like image 222
gigabytes Avatar asked Jul 02 '15 08:07

gigabytes


1 Answers

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.

like image 196
Angew is no longer proud of SO Avatar answered Oct 12 '22 05:10

Angew is no longer proud of SO