2015-07-02 12 views
15

La chiamata a std::min() con un elenco di inizializzazione vuoto di solito non viene compilata (tutta la domanda può essere dichiarata allo stesso modo per std::max()). Questo codice:Sta chiamando std :: min su un elenco inizializzatore vuoto (e specificando esplicitamente il tipo) comportamento non definito?

#include <iostream> 
#include <algorithm> 

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

Con clangore dà questo errore:

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) 

Posso capire perché questo caso non sarebbe stato permesso, perché è difficile essere d'accordo su un valore ragionevole di tornare in questo caso .

Tuttavia, tecnicamente parlando il codice non viene compilato solo perché non è possibile dedurre il parametro del modello. Se forzo il parametro il codice viene compilato ma ottengo un incidente:

#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 

Sembra che l'incidente si pone perché std::min() è implementato in termini di std::min_element(), ed una lista di inizializzazione vuota risultati nella dereference di un invalido end() iteratore.

Quindi questo comportamento del codice è indefinito in C++ 11/C++ 14? È std::min() dichiarato di non essere compilato quando chiamato senza parametri template espliciti? È stato specificato std::min() da implementare in termini di std::min_element()?

+0

Non mi aspettavo che facesse qualcosa in particolare. – gigabytes

+0

Sono d'accordo non c'è una buona risposta, in linea di principio. Lo dico anche nella domanda. Ma dal momento che un modo di invocarlo si compila e un altro no, ho chiesto se quello che compila fosse effettivamente specificato come UB. – gigabytes

risposta

22

Sì, è UB. Come 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.

(enfasi mia)

La stessa formulazione è presente in C++ 11 pure.

+0

Il mio male ... Ho guardato lo standard e per qualche motivo ho perso totalmente il requisito 't.size()> 0'! – gigabytes