0Pricing
C++ Academy · Lekcja

Pełna specjalizacja

Dostosowuj szablony do typu

Pełna specjalizacja to bezpłatna lekcja C++ Academy na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C++ Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C++ Academy zawiera 4 lekcji w sumie.

Podsumowanie: szablony

Szablon pozwala, aby jeden fragment kodu działał dla wielu typów. Kompilator generuje konkretną wersję dla każdego użytego typu.

  • Ogólna postać obsługuje każdy typ.
  • Czasami jeden typ wymaga specjalnego traktowania.
#include <iostream>

template <typename T>
T maxOf(T a, T b) { return a > b ? a : b; }

int main() {
    std::cout << maxOf(3, 9) << ' ' << maxOf(2.5, 1.5) << '\n';
    return 0;
}

Czym jest pełna specjalizacja?

Pełna specjalizacja udostępnia całkowicie osobną implementację dla jednego określonego typu, zastępując ogólny szablon wyłącznie dla tego typu.

#include <iostream>

template <typename T>
void describe(T) { std::cout << "some type\n"; }

template <>
void describe(int) { std::cout << "an int\n"; }

int main() {
    describe(3.14);
    describe(42);
    return 0;
}

Składnia

Pełna specjalizacja zaczyna się od pustych nawiasów ostrych template <> i zawiera dokładny typ w deklaracji specjalizacji.

#include <iostream>

template <typename T>
struct TypeName { static const char* get() { return "unknown"; } };

template <>
struct TypeName<bool> { static const char* get() { return "bool"; } };

int main() {
    std::cout << TypeName<double>::get() << '\n';
    std::cout << TypeName<bool>::get() << '\n';
    return 0;
}

Specjalizowanie szablonu klasy

Można specjalizować całe szablony klas, nadając danemu typowi własne składowe i zachowanie, odrębne od szablonu podstawowego.

#include <iostream>

template <typename T>
struct Storage {
    T value;
    void show() { std::cout << "value: " << value << '\n'; }
};

template <>
struct Storage<bool> {
    bool value;
    void show() { std::cout << (value ? "true" : "false") << '\n'; }
};

int main() {
    Storage<int> s{5}; s.show();
    Storage<bool> b{true}; b.show();
    return 0;
}

Dlaczego specjalizować?

Specjalizacja obsługuje typy wymagające innej logiki, na przykład const char*, dla którego potrzebne jest porównywanie łańcuchów zamiast porównywania wskaźników.

#include <iostream>
#include <cstring>

template <typename T>
bool equal(T a, T b) { return a == b; }

template <>
bool equal(const char* a, const char* b) { return std::strcmp(a, b) == 0; }

int main() {
    std::cout << std::boolalpha;
    std::cout << equal(5, 5) << '\n';
    std::cout << equal("hi", "hi") << '\n';
    return 0;
}

Specjalizowanie pojedynczej składowej

W przypadku szablonu klasy można specjalizować tylko jedną funkcję składową dla danego typu, zachowując pozostałe elementy.

#include <iostream>

template <typename T>
struct Printer {
    void print(T v) { std::cout << v << '\n'; }
};

template <>
void Printer<char>::print(char v) {
    std::cout << "char: " << v << '\n';
}

int main() {
    Printer<int>{}.print(7);
    Printer<char>{}.print('A');
    return 0;
}

Dopasowanie ma pierwszeństwo przed ogólną postacią

Gdy istnieje pełna specjalizacja dla dokładnego typu, kompilator zawsze wybiera ją zamiast szablonu podstawowego.

#include <iostream>

template <typename T>
int rank() { return 0; }

template <>
int rank<double>() { return 99; }

int main() {
    std::cout << rank<int>() << ' ' << rank<double>() << '\n';
    return 0;
}

Specjalizacja musi następować po szablonie podstawowym

Specjalizację należy zadeklarować po udostępnieniu szablonu podstawowego, ponieważ w przeciwnym razie kompilator nie ma czego specjalizować.

#include <iostream>

template <typename T>
const char* kind() { return "generic"; }

template <>
const char* kind<float>() { return "float"; }

int main() {
    std::cout << kind<int>() << ' ' << kind<float>() << '\n';
    return 0;
}

Specjalizowanie szablonów std

Można specjalizować niektóre szablony biblioteki standardowej, takie jak std::hash, dla własnych typów, aby działały z kontenerami haszującymi.

#include <iostream>

struct Point { int x, y; };

template <typename T>
struct Hasher { size_t operator()(const T&) { return 0; } };

template <>
struct Hasher<Point> {
    size_t operator()(const Point& p) { return p.x * 31 + p.y; }
};

int main() {
    Hasher<Point> h;
    std::cout << h(Point{2, 3}) << '\n';
    return 0;
}

Specjalizacja wartości

Parametry szablonu niebędące typami można specjalizować dla konkretnych wartości, co jest przydatne przy tworzeniu tabel używanych w czasie kompilacji.

#include <iostream>

template <int N>
struct Fib { static const int value = Fib<N-1>::value + Fib<N-2>::value; };

template <>
struct Fib<0> { static const int value = 0; };

template <>
struct Fib<1> { static const int value = 1; };

int main() {
    std::cout << Fib<10>::value << '\n';
    return 0;
}

Zachowanie musi pozostać spójne

Specjalizacja powinna zachowywać ten sam konceptualny kontrakt co szablon główny — zmienia się tylko implementacja. W przeciwnym razie kod wywołujący może działać w nieoczekiwany sposób.

#include <iostream>

template <typename T>
T zero() { return T{}; }

template <>
int zero<int>() { return 0; }

int main() {
    std::cout << zero<int>() << ' ' << zero<double>() << '\n';
    return 0;
}

Szybkie sprawdzenie

Proszę sprawdzić swoje rozumienie składni pełnej specjalizacji.

Podsumowanie

Poznali Państwo pełną specjalizację:

  • zapewnia dedykowaną implementację dla jednego dokładnego typu
  • jest zapisywana za pomocą template <> i konkretnego typu
  • kompilator zawsze wybiera dokładną specjalizację przed innymi dopasowaniami
  • działa dla funkcji, klas, pojedynczych składowych i konkretnych wartości

Następnie poznają Państwo częściową specjalizację, która dopasowuje wzorce typów.

Często zadawane pytania

Czy lekcja „Pełna specjalizacja” jest bezpłatna?

Tak — pełny tekst „Pełna specjalizacja” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C++ Academy, przejdź na CoddyKit PRO. Kurs C++ Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Pełna specjalizacja”?

Dostosowuj szablony do typu Ćwiczysz C++ Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć C++ Academy?

Nie wymagamy żadnego doświadczenia. C++ Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.

Ile czasu zajmuje lekcja „Pełna specjalizacja”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji C++ Academy?

Tak. Każda lekcja C++ Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Pełna specjalizacja
  2. Częściowa specjalizacja
  3. SFINAE
  4. Wzorce enable_if
← Powrót do C++ Academy