13.15 — Szablony aliasów

W lekcji 10.7 -- Typedefs i aliasy typów, omówiliśmy, w jaki sposób aliasy typów pozwalają nam zdefiniować alias dla istniejący typ.

Tworzenie aliasu typu dla szablonu klasy, w którym wszystkie argumenty szablonu są jawnie określone, działa tak samo jak normalny alias typu:

#include <iostream>

template <typename T>
struct Pair
{
    T first{};
    T second{};
};

template <typename T>
void print(const Pair<T>& p)
{
    std::cout << p.first << ' ' << p.second << '\n';
}

int main()
{
    using Point = Pair<int>; // utwórz alias typu normalnego
    Point p { 1, 2 };        // kompilator zastępuje to kompilatorem Pair<int>

    print(p);

    return 0;
}

Takie aliasy można definiować lokalnie (np. wewnątrz funkcji) lub globalnie.

Szablony aliasów

W innych przypadkach możemy potrzebować aliasu typu dla klasy szablonu, w której nie wszystkie argumentów szablonu są zdefiniowane jako część aliasu (i zamiast tego będą dostarczane przez użytkownika typu alias). W tym celu możemy zdefiniować szablon aliasu, który jest szablonem, którego można używać do tworzenia instancji aliasów typów. Podobnie jak aliasy typów nie definiują odrębnych typów, tak szablony aliasów nie definiują odrębnych typów.

Oto przykład, jak to działa:

#include <iostream>

template <typename T>
struct Pair
{
    T first{};
    T second{};
};

// Oto nasz szablon aliasu
// Szablony aliasów muszą być zdefiniowane w zasięgu globalnym
template <typename T>
using Coord = Pair<T>; // Współrzędny jest aliasem pary<T>

// Nasz szablon funkcji drukowania musi wiedzieć, że parametr szablonu Coorda T jest parametrem szablonu typu
template <typename T>
void print(const Coord<T>& c)
{
    std::cout << c.first << ' ' << c.second << '\n';
}

int main()
{
    Coord<int> p1 { 1, 2 }; // Przed C++-20: Musimy jawnie określić wszystkie argumenty szablonu typów
    Coord p2 { 1, 2 };      // W C++20 możemy użyć dedukcji szablonu aliasów, aby wydedukować argumenty szablonu w przypadkach, gdy CTAD działa

    std::cout << p1.first << ' ' << p1.second << '\n';
    print(p2);

    return 0;
}

W tym przykładzie definiujemy szablon aliasu o nazwie Coord jako alias dla Pair<T>, gdzie parametr szablonu typu T zostanie zdefiniowany przez użytkownika Coord alias. Coord jest szablonem aliasu i Coord<T> jest aliasem typu instancji dla Pair<T>. Po zdefiniowaniu możemy użyć Coord gdzie użyjemy Pair, i Coord<T> gdzie użyjemy Pair<T>.

W tym przykładzie warto zwrócić uwagę na kilka rzeczy.

Po pierwsze, w przeciwieństwie do aliasów typu normalnego (które można zdefiniować wewnątrz bloku), szablony aliasów muszą być zdefiniowane w zakresie globalnym (tak jak wszystkie szablony muszą).

Po drugie, przed C++20, musimy jawnie określić argumenty szablonu, gdy tworzymy instancję obiektu przy użyciu szablonu aliasu. Począwszy od C++20, możemy używać dedukcji szablonu aliasów, która wydedukuje typ argumentów szablonu z inicjatora w przypadkach, gdy typ aliasu działałby z CTAD.

Po trzecie, ponieważ CTAD nie działa na parametrach funkcji, kiedy używamy szablonu aliasu jako parametru funkcji, musimy jawnie zdefiniować argumenty szablonu używane przez szablon aliasu. Innymi słowy, robimy to:

template <typename T>
void print(const Coord<T>& c)
{
    std::cout << c.first << ' ' << c.second << '\n';
}

Nie to:

void print(const Coord& c) // nie zadziała, brakuje argumentów szablonu
{
    std::cout << c.first << ' ' << c.second << '\n';
}

To nie różni się od tego, gdybyśmy użyli Pair lub Pair<T> zamiast Coord lub Coord<T>.

guest
Twój adres e-mail nie zostanie wyświetlony
Znalazłeś błąd? Zostaw komentarz powyżej!
Komentarze związane z poprawkami zostaną usunięte po przetworzeniu, aby pomóc zmniejszyć bałagan. Dziękujemy za pomoc w ulepszaniu witryny dla wszystkich!
Awatary z https://gravatar.com/ są połączone z podanym adresem e-mail.
Powiadamiaj mnie o odpowiedziach:  
34 Komentarze
Najnowsze
Najstarsze Najczęściej głosowane
Wbudowane opinie
Wyświetl wszystkie komentarze