Šablony jsou základem pro univerzální programování v C++. C++ jako silně typovaný jazyk vyžaduje, aby všechny proměnné měly specifický typ, buď explicitně deklarovaný programátorem, nebo odvozený kompilátorem. Mnoho datových struktur a algoritmů však vypadá stejně bez ohledu na typ, na kterém pracují. Šablony umožňují definovat operace třídy nebo funkce a umožňují uživateli určit, jaké typy těchto operací by měly fungovat.

Definování a používání šablon

Šablona je konstrukce, která vytváří běžný typ nebo funkci v době kompilace na základě argumentů, které uživatel zadá pro parametry šablony. Můžete například definovat šablonu funkce takto:

šablona T minimum (const T& lhs, const T& rhs)

Výše uvedený kód popisuje šablonu obecné funkce s jedním parametrem typ T, návratovou hodnotu a parametry volání (lhs a rhs) všech těchto typů. Parametr typu můžete pojmenovat, jak chcete, ale podle konvence se nejčastěji používají jednohlavá písmena. T je parametr šablony; typové jméno Klíčové slovo říká, že tento parametr je zástupný symbol pro typ. Když je funkce volána, kompilátor nahradí každou instanci T argumentem specifického typu, buď zadaným uživatelem, nebo odvozeným kompilátorem. Proces, ve kterém kompilátor vytváří třídu nebo funkci ze šablony, se nazývá instance šablony. minimum Toto je instance minimální šablony.

Jinde může uživatel deklarovat instanci šablony specializované pro int. Předpokládejme, že get_a() a get_b() jsou funkce, které vracejí int:

int a = get_a(); int b = get_b(); int i = minimum(a, b); 

Protože se však jedná o šablonu funkce a kompilátor může odvodit typ T z argumentů a и b, můžete to volat stejně jako běžnou funkci:

int i = minimum(a, b); 

Když je nalezena poslední instrukce, kompilátor vytvoří novou funkci, ve které je každý výskyt T v šabloně je nahrazeno následujícím int cesta:

int minimum (const int& lhs, const int& rhs)

Pravidla pro to, jak kompilátor provádí odečítání typů v šablonách funkcí, jsou založena na pravidlech pro běžné funkce. Další informace naleznete v části Povolení přetížení volání šablon funkcí.

Parametry typu

Ve výše uvedené minimální šabloně si všimněte, že parametr typ T není vhodné, dokud není použito v parametrech volání funkce, kde jsou přidány konstantní a referenční kvalifikátory.

ČTĚTE VÍCE
Jak naředit Tornado na litr vody?

Neexistuje žádné praktické omezení počtu parametrů typu. Více parametrů oddělte čárkami:

template class Foo<>; 

Klíčové slovo třída ekvivalentní tomuto kontextu typové jméno . Předchozí příklad můžete vyjádřit takto:

template class Foo<>; 

Operátor elipsy (.) lze použít k definování vzoru, který přebírá libovolný počet parametrů typu nula nebo více:

template class vtclass; vtclass < >vtinstance1; vtclass vtinstance2; vtclass vtinstance3; 

Jako argument typu lze použít jakýkoli vestavěný nebo uživatelem definovaný typ. Například můžete použít std::vector ve standardní knihovně k uložení proměnných jako int , zdvojnásobit std::string, const MyClass MyClass *, MyClass&, atd. Hlavním omezením při používání šablon je, že argument typu musí podporovat všechny operace aplikované na parametry typu. Pokud například zavoláme minimální použití MyClass jako v následujícím příkladu:

class MyClass < public: int num; std::wstring description; >; int main() < MyClass mc1 ; MyClass mc2 ; auto result = minimum(mc1, mc2); // Error! C2678 > 

Je generována chyba kompilátoru, protože MyClass neposkytuje přetížení pro operátor.

Neexistuje žádný povinný požadavek, aby argumenty typu pro kteroukoli konkrétní šablonu patřily do stejné hierarchie objektů, i když je možné definovat šablonu, která takové omezení vynucuje. Objektově orientované metody můžete kombinovat se šablonami; Můžete například uložit derivaci* do vektoru. Všimněte si, že argumenty musí být ukazatele

vector vec; MyDerived d(3, L"back again", time(0)); vec.push_back(&d); // or more realistically: vector> vec2; vec2.push_back(make_shared()); 

Základní požadavky, které std::vector a další standardní knihovní kontejnery kladou na prvky T , které T lze přiřadit pomocí kopírování a vytváření kopie.

Netypové parametry

Na rozdíl od obecných typů v jiných jazycích, jako je C# a Java, podporují šablony C++ Volby, jiné než typy, nazývané také hodnotové parametry. Můžete například zadat celočíselnou konstantní hodnotu k označení délky pole, jako v tomto příkladu, podobně jako třída std::array ve standardní knihovně:

template class MyArray < T arr[L]; public: MyArray() < . >>; 

Všimněte si syntaxe v deklaraci šablony. Hodnota size_t je předána jako argument šablony při kompilaci a musí být const nebo výraz constexpr . Používáš to takto:

MyArray arr; 

Jiné typy hodnot, včetně ukazatelů a odkazů, lze předat jako parametry jiné než typ. Například můžete předat ukazatel na funkci nebo funkční objekt, abyste nakonfigurovali nějakou operaci v kódu šablony.

ČTĚTE VÍCE
Jak správně skladovat rybí konzervy?

Odečítání typu pro netypové parametry šablony

Ve Visual Studiu 2017 a novějších a v /std:c++17 režimu nebo novější, kompilátor odvodí typ argumentu šablony, který se liší od typu deklarovaného pomocí auto :

template constexpr auto constant = x; auto v1 = constant; // v1 == 5, decltype(v1) is int auto v2 = constant; // v2 == true, decltype(v2) is bool auto v3 = constant; // v3 == 'a', decltype(v3) is char 

Šablony jako parametry šablony

Šablona může být parametrem šablony. V tomto příkladu má MyClass2 dva parametry šablony: parametr typové jméno T a parametr Šablona Arr:

template class Arr> class MyClass2 < T t; //OK Arra; U u; //Error. U not in scope >; 

Protože já sám Arr parametr nemá žádný text, názvy jeho parametrů nejsou povinné. Ve skutečnosti je chybou odkazovat název typu nebo názvy parametrů třídy Arr z textu MyClass2. Z tohoto důvodu Názvy parametrů typu Arr lze vynechat, jak ukazuje tento příklad:

template class Arr> class MyClass2 < T t; //OK Arra; >; 

Výchozí argumenty šablony

Šablony tříd a funkcí mohou mít výchozí argumenty. Pokud má šablona výchozí argument, nemusí být při použití specifikován. Například šablona std::vector má výchozí argument pro alokátor:

template > class vector; 

Ve většině případů je platná výchozí třída std::allocator, takže se použije vektor, jak je ukázáno níže:

vector myInts; 

V případě potřeby však můžete zadat vlastní alokátor takto:

vector ints; 

Pokud existuje více argumentů šablony, všechny argumenty za prvním výchozím argumentem musí mít výchozí argumenty.

Při použití šablony, jejíž výchozí parametry jsou použity, použijte prázdné lomené závorky:

template class Bar < //. >; . int main() < Bar<>bar; // use all default type arguments > 

Specializace na šablony

V některých případech není možné nebo žádoucí definovat přesně stejný kód pro jakýkoli typ. Můžete například chtít definovat cestu ke kódu, který je třeba provést pouze v případě, že argument type je ukazatel nebo std::wstring nebo typ, který je odvozen z konkrétní základní třídy. V takových případech je možné určit specializace šablona pro konkrétní typ. Když uživatel vytvoří instanci šablony s tímto typem, kompilátor použije specializaci k vytvoření třídy a pro všechny ostatní typy zvolí kompilátor obecnější šablonu. Specializace, ve kterých jsou specializovány všechny parametry, jsou plné specializace. Pokud jsou specializované pouze některé parametry, nazývá se částečný specializace.

template class MyMap ; // partial specialization for string keys template class MyMap ; . MyMap classes; // uses original template MyMap classes2; // uses the partial specialization 

Šablona může mít libovolný počet specializací, pokud je každý parametr specializovaného typu jedinečný. Částečně specializované mohou být pouze šablony tříd. Všechny úplné a částečné specializace šablony musí být deklarovány ve stejném jmenném prostoru jako původní šablona.

ČTĚTE VÍCE
Je možné zasadit pivoňku bez kořenů?

Další informace najdete v tématu Specializace šablon.

Kontaktujte nás

Byly informace na této stránce užitečné?