2015-07-02 11 views
15

Aufruf von std::min() mit einer leeren Initialisierungsliste wird normalerweise nicht kompiliert (alle Fragen können für auf die gleiche Weise angegeben werden). Dieser Code:Ruft std :: min auf einer leeren Initialisierungsliste auf (und spezifiziert explizit den Typ) undefiniertes Verhalten?

#include <iostream> 
#include <algorithm> 

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

Mit Klirren gibt diesen Fehler:

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) 

Ich kann sehen, warum dieser Fall würde nicht erlaubt sein, weil es schwierig ist, auf einem vernünftigen Wert zu vereinbaren, in diesem Fall zurück .

Allerdings kompiliert der Code technisch nicht nur, weil der Vorlagenparameter nicht abgeleitet werden kann. Wenn ich die Parameter erzwingen der Code kompiliert, aber ich bekomme einen Absturz:

#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 

Es scheint der Absturz tritt auf, weil std::min() in Bezug auf std::min_element() implementiert ist, und eine leere Initialisiererliste führt in die Dereferenzierung eines ungültigen end() Iterator.

So ist dieses Stück Code undefiniertes Verhalten unter C++ 11/C++ 14? Wird std::min() angegeben, dass es nicht kompiliert wird, wenn es ohne explizite Template-Parameter aufgerufen wird? Wird std::min() spezifiziert in Bezug auf std::min_element()?

+0

Ich habe nicht erwartet, dass es etwas Besonderes tun. – gigabytes

+0

Ich stimme zu, es gibt im Prinzip keine gute Antwort. Ich sage es sogar in der Frage. Aber da eine Art, sie aufzurufen, kompiliert und eine andere nicht, fragte ich, ob die Kompilierung tatsächlich als UB spezifiziert wurde. – gigabytes

Antwort

22

Ja, es ist UB. Wie pro 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)

dieselbe Formulierung ++ in C 11 als auch anwesend ist.

+0

Meine schlechte ... Ich schaute auf den Standard und aus irgendeinem Grund habe ich die Anforderung 't.size()> 0 'total verpasst! – gigabytes