Witam w nowym roku. Dziś będzie o nowym elemencie szablonów czyli o szablonach ze zmienną liczbą parametrów. Ich implementacja i zachowanie różni się nieco od klasycznych szablonów.
Nowa funkcjonalność pozwala na tworzenie bezpiecznych list typów.
template<typename ...Ts>
void variadic_template(){}
Pierwszą nowością jest zastosowanie ...(wielokropka) przy określaniu typów szablonu. W ten sposób sygnalizujemy mnogość typów. Niestety nie mamy możliwości iterowania po kolejnych typach wewnątrz naszego szablonu. Ponadto taka definicja pozwala na stworzenie/wywołanie naszej szablonowej funkcji bez typów.
variadic_template<>();
Aby tego uniknąć można uciec się do następującej sztuczki:
template<typename T1, typename ...Ts>
void variadic_template(T1 arg, Ts... args)
W powyższym przykładzie jawnie wymuszamy podanie przynajmniej jednego typ dla naszej funkcji szablonowej.
Jak już wspomniałem nie możemy jawnie iterować po typach przekazanych do szablonu. Łatwo się domyślić że odbywa się to za pośrednictwem rekurencji zrzuconej na barki kompilatora (kod zostanie wygenerowany przez kompilator bez szkody dla czasu działania programu).
Przeanalizujmy zatem większy kawałek kodu:
template<typename T>
void handle(T arg)
{
std::cout<<"GENERIC\n";
}
template<>
void handle(int arg)
{
std::cout<<"INT: "<< arg <<std::endl;
}
template<>
void handle(double arg)
{
std::cout<<"DOUBLE: "<< arg <<std::endl;
}
template<typename T>
void variadic_template(T arg)
{
handle(arg);
}
template<typename T1, typename ...Ts>
void variadic_template(T1 arg, Ts... args)
{
variadic_template(arg);
variadic_template(args...);
}
wywołanie
variadic_template(1, 1.2, "asdas");
Wynik:
INT: 1
DOUBLE: 1.2
GENERIC
Szablonowa funkcja handle zajmuje się wykonaniem konkretnych zadań dla danych typów (jest specjalizowana dla typu int oraz double). Następnie widzimy specjalizację szblonu dla jednego typu która jednocześnie wywołuje na rzecz własnego argumentu funkcję handle. Kolejna funkcja szablonowa stanowi najciekawszy przypadek o zarazem demonstracje sposobu „iterowania” po typach z szablonu. Warto również zwrócić uwagę na dualne zastosowanie ...(wielokropka), raz pojawia się za słowem kluczowym typename i oznacza zmienną liczbę typów a raz pojawia się w prototypie funkcji gdzie oznacza zmienną liczbę parametrów. Przyglądając się funkcji variadic_template okazuje się że tak naprawdę wywołujemy własną specjalizację która to obsługuje konkretny argument konkretnego typu oraz wywołujemy rekurencyjnie variadic_template przekazując jako argument pozostałą listę argumentów. To wszystko. Kolejne wywołania powodują „zdjęcie” z listy kolejnych elementów na niej umieszczonych.
Komentarze
Prześlij komentarz