GCC secondo C++ 11 non può dedurre il tipo per le prime due chiamate su bar
. Avvisa perché implementa un'estensione da a C++ 11.
La norma dice che quando un argomento di funzione in una chiamata a un modello di funzione è un { ... }
e il parametro non è initializer_list<X>
(opzionalmente un parametro di riferimento), che poi il tipo di parametro non può essere dedotta dalla {...}
. Se il parametro è tale initializer_list<X>
, gli elementi dell'elenco di inizializzazione vengono dedotti in modo indipendente confrontando lo X
e ciascuna delle deduzioni degli elementi deve corrispondere.
template<typename T>
void f(initializer_list<T>);
int main() {
f({1, 2}); // OK
f({1, {2}}); // OK
f({{1}, {2}}); // NOT OK
f({1, 2.0}); // NOT OK
}
In questo esempio, il primo è OK, e il secondo è OK anche perché i primi rendimenti Elemento di int
, e il secondo elemento confronta {2}
contro T
- questa deduzione non può cedere un constradiction in quanto non è così dedurre qualsiasi cosa, quindi alla fine la seconda chiamata prende T
come int
. Il terzo non può dedurre T
da alcun elemento, quindi NON è OK. L'ultima chiamata produce detrazioni contraddittorie per due elementi.
Un modo per fare questo lavoro è quello di utilizzare un tale tipo come tipo di parametro
template <class T> void bar(std::initializer_list<std::initializer_list<T>> x) {
// ...
}
Vorrei sottolineare che facendo std::initializer_list<U>({...})
è pericoloso - meglio rimuovere quelli (...)
intorno le parentesi graffe. Nel tuo caso capita di lavorare per caso, ma prendere in considerazione
std::initializer_list<int> v({1, 2, 3});
// oops, now 'v' contains dangling pointers - the backing data array is dead!
La ragione è che ({1, 2, 3})
chiama il costruttore di copia/spostamento dei initializer_list<int>
passandogli un temporaneo initializer_list<int>
associato alla {1, 2, 3}
. L'oggetto temporaneo verrà quindi distrutto e muoiono al termine dell'inizializzazione. Quando l'oggetto temporaneo associato alla lista muore, anche l'array di backup contenente i dati verrà distrutto (se la mossa viene eliminata, vivrà fino a "v", che è male, poiché non si comporterebbe nemmeno male garantito!). Omettendo il paren, v
è direttamente associato all'elenco e i dati dell'array di supporto vengono distrutti solo quando viene distrutto v
.
possibile duplicato di [Perché il modello non accetta un elenco di inizializzazione] (http://stackoverflow.com/questions/4757614/why-doesnt-my-template-accept-an-initializer-list) - Quella domanda è fondamentalmente un duplicato. Il fatto che la deduzione dei tipi venga effettuata su una lista di inizializzatori è un'estensione g ++. – Omnifarious
@Sempre non sono sicuro se si tratta di questi. la mia domanda era intesa per chiedere meno dettagli di quella apparentemente questa domanda. –