2014-12-16 12 views
53

Questo è un follow-up di questa domanda: Is it legal to declare a constexpr initializer_list object?.Perché `std :: initializer_list` non è definito come un tipo letterale?

Da C++ 14, la classe std::initializer_list ha tutti i suoi metodi contrassegnati con constexpr. Sembra naturale poter inizializzare un'istanza eseguendo constexpr std::initializer_list<int> list = {1, 2, 3}; ma Clang 3.5 si lamenta del fatto che list non viene inizializzato da un'espressione costante. As dyp pointed out in a comment, qualsiasi requisito per std::initializer_list per essere un tipo letterale sembra essere svanito dalle specifiche.

Qual è il punto di avere una classe completamente definita come constexpr se non è possibile inizializzarla come tale? È una svista nello standard e verrà risolto in futuro?

+0

Richard Smith sembra implicare [qui] (http: //clang-developers.42468.n3.nabble.com/C-11-constexpr-and-initializer-list-td4031078.html) che 'std :: initializer_list' è stato reso un tipo letterale. Tuttavia, non riesco a trovare un tale requisito nello standard. Una seconda domanda, che ho postato su un commento alla mia domanda collegata sopra, è * "Può le funzioni membro non statiche di constexpr essere dichiarate come membri di tipi non letterali?" *, Vedi [CWG DR 1684] (http: //open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1684) – dyp

+0

Questo è strano, clang ++ compila questo quando lo metti nello scope globale: http://coliru.stacked-crooked.com/a/dab2834181fb8ea4 (Questo era [clang bug 15117] (http://llvm.org/bugs/show_bug.cgi?id=15117)) Sente l'odore di un altro bug del compilatore. – dyp

+0

clang ++ accetta anche quando è una variabile statica locale: http://coliru.stacked-crooked.com/a/700cf33e2446b63c – dyp

risposta

5

Il comitato standard sembra intenzionato su initializer_list di tipo letterale. Tuttavia, non sembra che sia un requisito esplicito e sembra essere un bug nello standard.

Da § 3.9.10.5:

Un tipo è un tipo letterale se è:
- un tipo di classe (Clausola 9) che ha tutte le seguenti proprietà:
- - ha un distruttore banale,
- - è un tipo di aggregato (8.5.1) o ha almeno un constexpr costruttore o costruttore modello che non è una copia o spostare costruttore e
- - tutta la sua non membro statistico s e le classi base sono di tipo letterale non volatile.

Da § 18.9.1:

namespace std { 
    template<class E> class initializer_list { 
    public: 
    /* code removed */ 
    constexpr initializer_list() noexcept; 
    // No destructor given, so trivial 
    /* code removed */ 
    }; 
} 

Questo soddisfa il primo e secondo requisiti.

Per la terza condizione però:

Da § 18.9.2 (enfasi mia):

Un oggetto di tipo initializer_list<E> fornisce accesso ad un array di oggetti di tipo const E. [Nota: Una coppia di puntatori o un puntatore più una lunghezza sarebbero rappresentazioni ovvie per initializer_list. initializer_list viene utilizzato per implementare gli elenchi di inizializzatori come specificato in 8.5.4. La copia di un elenco di inizializzazione non copia gli elementi sottostanti.
-end nota]

Quindi non v'è alcun obbligo per i membri privati ​​della realizzazione di initializer_list essere tipi letterali non volatili; tuttavia, poiché menzionano che credono che una coppia di puntatori o un puntatore e una lunghezza sarebbero la "rappresentazione ovvia", probabilmente non ritengono che qualcuno possa mettere qualcosa di non letterale nei membri di initializer_list.

Direi che è sia un bug in clang che lo standard, probabilmente.

Problemi correlati