ProgrammazioneSviluppatore C++, Sviluppatore Senior

Come funzionano i modelli di funzioni e classi con parametri predefiniti? Quali sono le sottigliezze del loro utilizzo e cosa fare in caso di conflitti tra funzioni modello e funzioni non modello?

Supera i colloqui con l'assistente IA Hintsage

Risposta.

I modelli con parametri predefiniti sono un potente meccanismo di programmazione generica in C++.

Storia della questione:

La libreria STL è partita dai modelli. In seguito è stata introdotta la possibilità di specificare valori predefiniti per i parametri sia delle funzioni modello che delle classi, al fine di rendere i modelli più universali e supportare l'estensibilità del codice.

Problema:

Possono verificarsi conflitti non evidenti quando ci sono sovraccarichi di funzioni normali e modelli, così come ambiguità nelle specializzazioni. I parametri predefiniti nei modelli possono aumentare la flessibilità, ma spesso portano a errori di compilazione confusi.

Soluzione:

È meglio minimizzare il numero di valori predefiniti nei modelli, specialmente se ci sono sovrapposizioni con versioni non modello. La priorità nella chiamata delle funzioni preferisce una corrispondenza esatta con una funzione normale, piuttosto che con una modello.

Esempio di codice:

template<typename T = int> T multiply(T a, T b = T(2)) { return a * b; } int multiply(int a, int b) { return a + b; }

La chiamata multiply(5, 4) selezionerà la funzione int multiply(int, int), mentre la chiamata multiply<>(5) chiamerà il modello, e b assumerà il valore 2.

Caratteristiche chiave:

  • I valori predefiniti sono dichiarati solo nella prima dichiarazione/definizione del modello.
  • Le funzioni normali hanno priorità sui modelli in caso di corrispondenza delle firme.
  • I valori predefiniti per i parametri dei modelli si applicano solo in assenza di una chiamata esplicita.

Domande trabocchetto.

È possibile dichiarare valori predefiniti in una definizione successiva di una funzione modello?

No, il valore predefinito può essere specificato solo in un luogo (di solito nella dichiarazione), altrimenti si verifica un errore di compilazione.

Cosa succede in caso di ambiguità tra un modello e una funzione non modello? Come sceglie il compilatore quale chiamare?

Il compilatore darà sempre priorità alla funzione non modello se si adatta esattamente agli argomenti. La funzione modello verrà chiamata solo in assenza di una corrispondenza esatta.

È possibile specificare valori predefiniti per un parametro non tipo di un modello (ad esempio, per un numero)?

Sì, per esempio:

template<typename T, int N = 8> class Array { T data[N]; };

Errori tipici e anti-pattern

  • Dichiarazione di valori predefiniti simultaneamente in più posti.
  • Ambiguità implicita tra funzioni modello e normali.
  • Uso eccessivo di parametri predefiniti, che rendono difficile la lettura e il debug del codice.

Esempio dalla vita reale

Caso negativo

Sia dichiarata una funzione modello che una non modello con parametri e valori predefiniti corrispondenti. In un modulo la chiamata funziona come previsto, mentre in un altro viene inaspettatamente scelta una versione errata della funzione.

Pro:

  • Comodo chiamare senza specificare il tipo.

Contro:

  • Errori non evidenti e logica di chiamata confusa.

Caso positivo

Per le configurazioni sovrapposte, sono stati dichiarati esplicitamente nomi diversi per le funzioni modello e non modello, con valori predefiniti solo su una delle versioni.

Pro:

  • Comportamento esplicito.
  • Nessuna collisione nella chiamata.

Contro:

  • Un po' più di codice nella gestione delle versioni della funzione.