initializer_list e deduzione del tipo di modello

Considera la funzione:

template void printme(T&& t) { for (auto i : t) std::cout << i; } 

o qualsiasi altra funzione che si aspetta un parametro con un tipo abilitato begin () / end ().

Perché il seguente è illegale?

printme({'a', 'b', 'c'});

Quando tutti questi sono legittimi:

 printme(std::vector({'a', 'b', 'c'})); printme(std::string("abc")); printme(std::array {'a', 'b', 'c'}); 

Possiamo persino scrivere questo:

 const auto il = {'a', 'b', 'c'}; printme(il); 

o

 printme<std::initializer_list>({'a', 'b', 'c'}); 

Il tuo printme({'a', 'b', 'c'}) prima riga printme({'a', 'b', 'c'}) è illegale perché non è stato ansible dedurre l’argomento del modello T Se si specifica esplicitamente l’argomento del modello, funzionerà, ad esempio printme>({'a', 'b', 'c'}) o printme>({'a', 'b', 'c'}) .

Gli altri che hai elencato sono legali perché l’argomento ha un tipo ben definito, quindi l’argomento del modello T può essere dedotto bene.

Anche lo snippet con auto funziona perché il è considerato di tipo std::initializer_list , e quindi l’argomento del template su printme() può essere dedotto.


L’unica parte “divertente” qui è che auto sceglierà il tipo std::initializer_list ma l’argomento template non lo farà. Questo perché il § 14.8.2.5/5 dello standard C ++ 11 afferma esplicitamente che questo è un contesto non dedotto per un argomento modello:

Un parametro di funzione per il quale l’argomento associato è un elenco di inizializzazione (8.5.4) ma il parametro non ha std :: initializer_list o riferimento a un ansible tipo std :: initializer_list qualificato cv. [Esempio:

 template void g(T); g({1,2,3}); // error: no argument deduced for T 

– esempio finale]

Tuttavia con auto , il § 7.1.6.4/6 ha il supporto esplicito per std::initializer_list<>

se l’inizializzatore è un bretelle-init-list (8.5.4), con std::initializer_list .

Puoi anche sovraccaricare la funzione per prendere esplicitamente un argomento di tipo initializer_list.

 template void printme(std::initializer_list t) { for (auto i : t) std::cout << i; } 

Questo è specificamente coperto dal § 14.8.2.5/5

Un parametro di funzione per il quale l’argomento associato è un elenco di inizializzazione ma il parametro non ha std::initializer_list o riferimento a un ansible tipo std::initializer_list qualificato cv. [ Esempio:

 template void g(T); g({1,2,3}); // error: no argument deduced for T 

-End esempio]

Per farlo funzionare, è ansible specificare il tipo di argomento del modello in modo esplicito.

 printme>( {1,2,3,4} );