正在对空的初始值设定项列表调用std::min(并显式指定类型)未定义的行为

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

本文关键字:min 类型 未定义 调用 列表 std      更新时间:2023-10-16

用空的初始值设定项列表调用std::min()通常不会编译(所有问题都可以用与std::max()相同的方式陈述)。此代码:

#include <iostream>
#include <algorithm>
int main() {
   std::cout << std::min({}) << "n";
   return 0;
}

与clang给出这个错误:

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)

我明白为什么这种情况不被允许,因为在这种情况下很难就合理的回报价值达成一致。

然而,从技术上讲,代码并不只是因为模板参数无法推导而编译的。如果我强制参数,代码会编译,但我会崩溃:

#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

崩溃的出现似乎是因为std::min()是根据std::min_element()实现的,并且空的初始化器列表导致无效的end()迭代器的取消引用。

那么,这段代码在C++11/C++14下是未定义的行为吗?在没有显式模板参数的情况下调用std::min()时,是否声明不编译?std::min()是否规定按照std::min_element()执行?

是的,它是UB。根据C++14(n4140)25.4.7/4:

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

4需要:TLessThanComparableCopyConstructible以及t.size() > 0

(强调矿)

C++11中也有同样的措辞。