Częściowa specjalizacja
Specjalizuj wzorce szablonów
Częściowa specjalizacja to bezpłatna lekcja C++ Academy na CoddyKit. To lekcja 2 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.
Czym jest częściowa specjalizacja
Częściowa specjalizacja dostosowuje szablon do rodziny typów współdzielących określony wzorzec, a nie do jednego dokładnego typu.
- Obsługują ją wyłącznie szablony klas.
- Część parametrów pozostaje ogólna.
#include <iostream>
template <typename T>
struct Traits { static const char* kind() { return "value"; } };
template <typename T>
struct Traits<T*> { static const char* kind() { return "pointer"; } };
int main() {
std::cout << Traits<int>::kind() << '\n';
std::cout << Traits<int*>::kind() << '\n';
return 0;
}Dopasowywanie wskaźników
Wzorzec T* pasuje do dowolnego typu wskaźnikowego, dzięki czemu można obsłużyć wszystkie wskaźniki za pomocą jednej specjalizacji.
#include <iostream>
template <typename T>
struct Deref { static T get(T v) { return v; } };
template <typename T>
struct Deref<T*> { static T get(T* p) { return *p; } };
int main() {
int x = 42;
std::cout << Deref<int>::get(7) << '\n';
std::cout << Deref<int*>::get(&x) << '\n';
return 0;
}Funkcji nie można częściowo specjalizować
Tylko szablony klas (i zmiennych) obsługują częściową specjalizację. W przypadku funkcji należy użyć przeciążania.
#include <iostream>
template <typename T>
void show(T) { std::cout << "value\n"; }
template <typename T>
void show(T*) { std::cout << "pointer\n"; }
int main() {
int x = 0;
show(5);
show(&x);
return 0;
}Specjalizacja jednego z dwóch parametrów
W przypadku wielu parametrów typów można ustalić jeden z nich, a drugi pozostawić otwarty, dopasowując wzorzec obejmujący różne typy.
#include <iostream>
template <typename A, typename B>
struct Pair { static const char* kind() { return "mixed"; } };
template <typename A>
struct Pair<A, A> { static const char* kind() { return "same types"; } };
int main() {
std::cout << Pair<int, double>::kind() << '\n';
std::cout << Pair<int, int>::kind() << '\n';
return 0;
}Dopasowywanie tablic
Typy tablic można dopasowywać za pomocą wzorca, który przechwytuje typ elementu i rozmiar jako parametr szablonu niebędący typem.
#include <iostream>
template <typename T>
struct Info { static int size() { return 1; } };
template <typename T, int N>
struct Info<T[N]> { static int size() { return N; } };
int main() {
std::cout << Info<int>::size() << '\n';
std::cout << Info<int[5]>::size() << '\n';
return 0;
}Wzorce const
Specjalizacja może usuwać kwalifikator const lub go wykrywać, dopasowując const T jako wzorzec.
#include <iostream>
template <typename T>
struct IsConst { static const bool value = false; };
template <typename T>
struct IsConst<const T> { static const bool value = true; };
int main() {
std::cout << std::boolalpha;
std::cout << IsConst<int>::value << '\n';
std::cout << IsConst<const int>::value << '\n';
return 0;
}Pierwszeństwo ma najbardziej wyspecjalizowana
Gdy pasować może kilka specjalizacji, kompilator wybiera najbardziej wyspecjalizowaną, czyli tę o najbardziej szczegółowym wzorcu.
#include <iostream>
template <typename T>
struct K { static int v() { return 0; } };
template <typename T>
struct K<T*> { static int v() { return 1; } };
template <>
struct K<int*> { static int v() { return 2; } };
int main() {
std::cout << K<double*>::v() << ' ' << K<int*>::v() << '\n';
return 0;
}Wzorce referencji
Można również dopasowywać typy referencyjne, odróżniając referencję od zwykłej wartości.
#include <iostream>
template <typename T>
struct Cat { static const char* k() { return "value"; } };
template <typename T>
struct Cat<T&> { static const char* k() { return "lvalue ref"; } };
int main() {
std::cout << Cat<int>::k() << '\n';
std::cout << Cat<int&>::k() << '\n';
return 0;
}Tworzenie cech typów
Częściowa specjalizacja stanowi podstawę cech typów. Oto samodzielnie zaimplementowana cecha remove_pointer.
#include <iostream>
#include <type_traits>
template <typename T>
struct RemovePtr { using type = T; };
template <typename T>
struct RemovePtr<T*> { using type = T; };
int main() {
std::cout << std::boolalpha;
std::cout << std::is_same<RemovePtr<int*>::type, int>::value << '\n';
return 0;
}Łączenie wzorców
Można łączyć wzorce, na przykład dopasowując wskaźnik do const, aby obsługiwać wielowarstwowe struktury typów.
#include <iostream>
template <typename T>
struct Desc { static const char* k() { return "plain"; } };
template <typename T>
struct Desc<const T*> { static const char* k() { return "ptr to const"; } };
int main() {
std::cout << Desc<int>::k() << '\n';
std::cout << Desc<const int*>::k() << '\n';
return 0;
}Praktyczna cecha kontenera
Za pomocą częściowej specjalizacji można wyodrębnić typ elementu z szablonu przypominającego kontener.
#include <iostream>
#include <type_traits>
template <typename C>
struct Element { using type = void; };
template <template <typename> class C, typename T>
struct Element<C<T>> { using type = T; };
template <typename T>
struct Box { T item; };
int main() {
std::cout << std::boolalpha;
std::cout << std::is_same<Element<Box<int>>::type, int>::value << '\n';
return 0;
}Szybkie sprawdzenie
Proszę sprawdzić swoje rozumienie częściowej specjalizacji.
Podsumowanie
Poznali Państwo częściową specjalizację:
- dostosowuje szablon klasy do wzorca typów, takiego jak
T*lubconst T - w przypadku funkcji używa się przeciążania, a nie częściowej specjalizacji
- wybierana jest najlepiej dopasowana, najbardziej wyspecjalizowana wersja
- stanowi podstawę cech typów, takich jak
remove_pointer
Następnie poznają Państwo SFINAE — mechanizm pozwalający włączać funkcje tylko wtedy, gdy typ spełnia wymagania.
Często zadawane pytania
Czy lekcja „Częściowa specjalizacja” jest bezpłatna?
Tak — pełny tekst „Częściowa 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 „Częściowa specjalizacja”?
Specjalizuj wzorce szablonów Ć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 2 z 4.
Ile czasu zajmuje lekcja „Częściowa 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
- Pełna specjalizacja
- Częściowa specjalizacja
- SFINAE
- Wzorce enable_if