0Pricing
C++ Academy · Lezione

Specializzazione completa

Personalizzare i template per un tipo

Specializzazione completa è una lezione C++ Academy gratuita su CoddyKit. Questa è la lezione 1 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento C++ Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso C++ Academy include 4 lezioni in totale.

Riepilogo: template

Un template permette a un frammento di codice di funzionare con molti tipi. Il compilatore genera una versione concreta per ogni tipo utilizzato.

  • La forma generale gestisce ogni tipo.
  • A volte un tipo richiede un trattamento speciale.
#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;
}

Che cos'è la specializzazione completa?

La specializzazione completa fornisce un'implementazione completamente separata per un tipo specifico, sostituendo il template generale solo per quel tipo.

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

La sintassi

Una specializzazione completa inizia con parentesi angolari vuote template <> e indica il tipo esatto nella specializzazione.

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

Specializzare un class template

È possibile specializzare interamente i class template, assegnando a un tipo membri e comportamenti propri, distinti da quelli del template primario.

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

Perché specializzare?

La specializzazione gestisce i tipi che richiedono una logica diversa, ad esempio const char*, che richiede il confronto tra stringhe anziché il confronto tra puntatori.

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

Specializzare un singolo membro

Per un class template è possibile specializzare una sola funzione membro per un determinato tipo, riutilizzando tutte le altre.

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

La corrispondenza prevale sulla generalità

Quando esiste una specializzazione completa per il tipo esatto, il compilatore la preferisce sempre al template primario.

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

La specializzazione deve seguire il template primario

Una specializzazione deve essere dichiarata dopo che il template primario è visibile; altrimenti il compilatore non ha nulla da specializzare.

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

Specializzare i template std

È possibile specializzare alcuni template della libreria standard, come std::hash, per i propri tipi, così da poterli usare con i contenitori hash.

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

Specializzazione per valore

I parametri di template non di tipo possono essere specializzati in base a valori specifici, una soluzione utile per le tabelle generate a tempo di compilazione.

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

Mantenere coerente il comportamento

Una specializzazione dovrebbe mantenere lo stesso contratto concettuale del template primario e modificare soltanto l'implementazione. In caso contrario, il codice chiamante può ottenere risultati inattesi.

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

Verifica rapida

Verifichi la Sua comprensione della sintassi della specializzazione completa.

Riepilogo

Ha imparato a conoscere la specializzazione completa:

  • fornisce un'implementazione dedicata per un solo tipo esatto
  • si scrive con template <> e il tipo concreto
  • il compilatore dà sempre la precedenza a una specializzazione esatta
  • funziona per funzioni, classi, singoli membri e valori specifici

Successivamente, vedrà la specializzazione parziale, che corrisponde a pattern di tipi.

Domande Frequenti

La lezione «Specializzazione completa» è gratuita?

Sì — il testo completo di «Specializzazione completa» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso C++ Academy, passa a CoddyKit PRO. Il corso C++ Academy include 4 lezioni in totale.

Cosa imparerò in «Specializzazione completa»?

Personalizzare i template per un tipo Eserciti C++ Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare C++ Academy?

Non è richiesta alcuna esperienza precedente. C++ Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 4.

Quanto tempo richiede la lezione «Specializzazione completa»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione C++ Academy?

Sì. Ogni lezione C++ Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Specializzazione completa
  2. Specializzazione parziale
  3. SFINAE
  4. Pattern con enable_if
← Torna a C++ Academy