Skip to content

Overload Resolution e Funzioni Variadiche

Overload Resolution (Risoluzione del Sovraccarico)

Section titled “Overload Resolution (Risoluzione del Sovraccarico)”

Hai diverse funzioni con lo stesso nome, e ne invochi una. Che passaggi compie la mente del compilatore per “eleggere” la variante corretta che andrà a compilare?

L’ordine di preferenza del C++ è ferreo:

  1. Match Esatto: Cerca una funzione i cui tipi dei parametri combacino esattamente.
  2. Promozione: Prova le promozioni sicure (es. short promosso a int, float a double).
  3. Conversione Standard: Prova cast più disperati (es. int castato a double, o puntatore castato in void*).
  4. Conversioni Utente: Prova a usare i metodi di Cast personalizzati delle Classi.
  5. Funzioni Variadiche: Se fallisce tutto, usa una “catch-all” variadica. Se nessuna (o se più di una) vince, otterrai un mortale errore Ambiguous Call.

Prendi la funzione printf. Accetta un numero letteralmente infinito e ignoto di parametri. Nel vecchio C questo si realizzava mettendo ... come ultimo parametro della firma, per poi usare macchinose e pericolosissime macro (come va_list o va_start dell’header <cstdarg>) per “estrarli” uno ad uno.

Questo approccio non era “Type-Safe”: il compilatore non aveva idea di che tipi passassi, per quello printf esige la stringa “%d”, “%f” per farsi spiegare da te cosa diavolo estrarre dalla memoria. Non usarle.

Nel C++ moderno usiamo i Template per risolvere elegantemente la ricezione di infiniti argomenti: si dichiarano con il prefisso magico typename... Args chiamato Template Parameter Pack (Pacco di Parametri).

Questi argomenti non sono array. Esistono a tempo di compilazione. Non puoi farci un loop for dentro! Devi esplorarli usando la Ricorsione a Compile-Time (una funzione che mangia il primo argomento, per poi auto-richiamarsi ripassandosi tutti i rimanenti, finché non restano a zero e si ferma in un base-case).

Siamo onesti: implementare una funzione ricorsiva complessa per fare una volgare addizione di parametri è macchinoso. Nel C++17 è atterrata un’altra feature strepitosa per consumare all’istante i Parameter Pack: le Fold Expressions.

Specificando l’operatore tra parentesi puntato verso il pack, lui “collasserà” tutti gli elementi tra di loro: (... + args)

// La stessa esatta funzione ricorsiva di prima, annientata in una riga C++17!
template <typename... T>
constexpr auto sum(T... args) {
return (... + args);
}

Questa sintassi compatta permette ai maghi del C++ di comporre algoritmi flessibilissimi!