C++ Academy · Lektion

Delvis specialisering

Specialisér templatemønstre

Lektion 2 af 413 trin

Delvis specialisering er en gratis C++ Academy-lektion på CoddyKit. Dette er lektion 2 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i C++ Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. C++ Academy-kurset indeholder 4 lektioner i alt.

Hvad er delvis specialisering?

Delvis specialisering tilpasser en skabelon til en familie af typer, der deler et mønster, i stedet for til én bestemt type.

  • Det understøttes kun af klasseskabeloner.
  • Du lader stadig nogle parametre være generiske.
#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;
}

Matchning af pegere

Mønstret T* matcher enhver pegetype, så du kan håndtere alle pegere med én specialisering.

#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;
}

Funktioner kan ikke delvist specialiseres

Kun klasse- og variabelskabeloner understøtter delvis specialisering. Til funktioner bruger du i stedet overbelastning.

#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;
}

Specialisering af én af to parametre

Med flere typeparametre kan du fastlåse den ene og lade den anden være åben, så du matcher et mønster på tværs af typer.

#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;
}

Matchning af arrays

Du kan matche arraytyper med et mønster, der opfanger elementtypen og størrelsen som en parameter, der ikke er en type.

#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;
}

Const-mønstre

En specialisering kan fjerne eller registrere const ved at matche const T som et mønster.

#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;
}

Den mest specialiserede vinder

Når flere specialiseringer kan matche, vælger kompileren den mest specialiserede, altså det mønster, der er mest specifikt.

#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;
}

Referencemønstre

Du kan også matche referencetyper, så du kan skelne en reference fra en almindelig værdi.

#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;
}

Opbygning af typeegenskaber

Delvis specialisering er motoren bag typeegenskaber. Her er en håndskrevet 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;
}

Kombinering af mønstre

Du kan kombinere mønstre, for eksempel matche en peger til const for at håndtere lagdelte typestrukturer.

#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;
}

En praktisk containeregenskab

Brug en delvis specialisering til at udtrække elementtypen fra en containerlignende skabelon.

#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;
}

Hurtigt tjek

Afprøv din forståelse af delvis specialisering.

Opsummering

Du har lært om delvis specialisering:

  • tilpasser en klasseskabelon til et mønster af typer som T* eller const T
  • funktioner bruger overbelastning, ikke delvis specialisering
  • den mest specialiserede matchende version vælges
  • den danner grundlaget for typeegenskaber som remove_pointer

Dernæst skal du lære om SFINAE, som gør det muligt kun at aktivere funktioner, når en type opfylder betingelserne.

Gratis at komme i gang

Lær C++ med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
51
Lektioner
203

Ofte stillede spørgsmål

Er lektionen “Delvis specialisering” gratis?

Ja — alle 3 lektioner i læringssporet C++ Academy, inklusive “Delvis specialisering”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. C++ Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Delvis specialisering”?

Specialisér templatemønstre Du øver dig i C++ Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på C++ Academy?

Der kræves ingen tidligere erfaring. C++ Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 2 af 4.

Hvor lang tid tager lektionen “Delvis specialisering”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne C++ Academy-lektion?

Ja. Alle C++ Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Fuld specialisering
  2. Delvis specialisering
  3. SFINAE
  4. enable_if-mønstre
← Tilbage til C++ Academy