initializer_list und Vorlagentyp Abzug

Betrachten Sie die function:

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

oder jede andere function, die einen Parameter mit einem begin () / end () – aktivierten Typ erwartet.

Warum ist das Folgende illegal?

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

Wenn all dies legitim ist:

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

Wir können das sogar schreiben:

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

oder

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

Ihre erste Zeile printme({'a', 'b', 'c'}) ist unzulässig, da das Vorlagenargument T nicht abgeleitet werden konnte. Wenn Sie das Template-Argument explizit angeben, funktioniert es, zB printme>({'a', 'b', 'c'}) oder printme>({'a', 'b', 'c'}) .

Die anderen, die Sie aufgelistet haben, sind legal, weil das Argument einen wohldefinierten Typ hat, so dass das Template-Argument T gut abgeleitet werden kann.

Ihr Snippet mit auto funktioniert auch, weil il als vom Typ std::initializer_list wird und daher das Template-Argument für printme() abgeleitet werden kann.


Der einzige “lustige” Teil hier ist, dass auto den Typ std::initializer_list auswählt, aber das Template-Argument nicht. Dies liegt daran, dass § 14.8.2.5/5 des C ++ 11-Standards explizit besagt, dass dies ein nicht-abgeleiteter Kontext für ein Template-Argument ist:

Ein functionsparameter, dessen zugehöriges Argument eine Initialisierungsliste (8.5.4) ist, aber der Parameter hat keine std :: initializer_list oder Referenz auf einen möglicherweise cv-qualifizierten std :: initializer_list-Typ. [Beispiel:

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

– Ende Beispiel]

Jedoch hat § 7.1.6.4/6 bei auto explizite Unterstützung für std::initializer_list<>

Wenn der Initialisierer eine braced -init-Liste (8.5.4) ist, mit std::initializer_list .

Sie können die function auch überladen, um explizit ein Argument vom Typ initializer_list zu übernehmen.

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

Dies ist insbesondere in § 14.8.2.5/5 geregelt

Ein functionsparameter, für den das zugehörige Argument eine Initialisierungsliste ist, aber der Parameter std::initializer_list oder Verweis auf möglicherweise cv-qualifizierten std::initializer_list Typ nicht hat. [Beispiel:

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

-End-Beispiel]

Damit es funktioniert, können Sie den Vorlagenargumenttyp explizit angeben.

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