Achtergrond van de vraag:
Sjablonen werden toegevoegd aan C++ voor een effectieve implementatie van algemene algoritmen en gegevensstructuren. Van het begin af aan was er behoefte aan een mechanisme voor automatische typeafleiding op basis van de invoerargumenten, om het gebruik van sjablonen handiger te maken voor de ontwikkelaar.
Probleem:
Het afleidingsmechanisme is niet altijd duidelijk: er ontstaat ambiguïteit met referenties, type-masquerading, gedeeltelijke specialisaties, sjabloonparameters-referenties en constanten. Soms kan de compiler het type niet afleiden of levert het een onverwacht resultaat op.
Oplossing:
De compiler analyseert de argumenten, vergelijkt ze met sjabloonparameters, rekening houdend met de regels van cv-kwalificatoren, referenties en pointers. Gebreken en beperkingen vereisen expliciete type-aanduiding wanneer automatische afleiding niet mogelijk is.
Codevoorbeeld:
template<typename T> void func(T arg) { /* ... */ } func(10); // T afgeleid als int func("abc"); // T afgeleid als const char* // Verschil tussen T arg en T& arg: template<typename T> void printRef(T& arg); // Accepteert geen tijdelijke objecten!
Belangrijke kenmerken:
Wat gebeurt er als een sjabloonfunctie T& accepteert en je probeert een tijdelijk object door te geven?
De compiler kan het type niet afleiden, omdat een tijdelijk object niet via een niet-const referentie kan worden doorgegeven. Er ontstaat een compileerfout.
template<typename T> void foo(T& arg); foo(42); // Fout!
Hoe werkt typeafleiding met arrays?
Arrays „decay” naar pointers bij doorgeven per waarde, maar als het sjabloon een referentie accepteert, blijft de grootte van de array behouden, wat vaak wordt gebruikt voor het implementeren van veilige sjabloon-templates.
template<typename T, size_t N> void arraySize(T (&arr)[N]) { std::cout << N; } int x[10]; arraySize(x); // Geeft 10 weer
Waarom is het niet altijd correct om auto te gebruiken voor het opslaan van resultaten van sjabloonfunctieaanroepen?
Auto kan bij typeafleiding „slicen” van const of ref-kwalificatoren, wat soms leidt tot onverwachte fouten bij kopiëren of aanpasbaarheid.
auto x = funcReturningRef(); // x zal per waarde zijn, en niet als referentie!
Een sjabloonfunctie voor algemene sortering accepteert T&, de gebruiker probeert een tijdelijk object door te geven. Het resultaat is dat de code niet compileert, en de fout leidt tot verwarring bij de ontwikkelaar.
Voordelen:
Nadelen:
De sorter is geïmplementeerd met universele referenties (T&&) met behulp van std::forward, wat het mogelijk maakt om zowel met lvalue als rvalue om te gaan, waardoor de prestaties en flexibiliteit worden verhoogd.
Voordelen:
Nadelen: