Template Metaprogramming – Differenza tra l’uso di Enum Hack e Static Const

Mi chiedo quale sia la differenza tra l’uso di un const statico e un enum hack quando si usano le tecniche di metaprogrammazione del modello.

EX: (Fibonacci via TMP)

template struct TMPFib { static const int val = TMPFib::val + TMPFib::val; }; template struct TMPFib { static const int val = 1; }; template struct TMPFib { static const int val = 0; }; 

vs.

 template struct TMPFib { enum { val = TMPFib::val + TMPFib::val }; }; template struct TMPFib { enum { val = 1 }; }; template struct TMPFib { enum { val = 0 }; }; 

Perché usarne uno sull’altro? Ho letto che l’enum hack è stato usato prima che il const statico fosse supportato all’interno delle classi, ma perché usarlo adesso?

Le enumerazioni non sono lvals, i valori dei membri statici sono e se passati per riferimento il modello verrà instanciato:

 void f(const int&); f(TMPFib<1>::value); 

Se vuoi fare calcoli di tempo di compilazione, ecc. Questo è un indesiderato effetto collaterale.

La principale differenza storica è che le enumerazioni funzionano anche per i compilatori in cui l’inizializzazione in class dei valori dei membri non è supportata, ciò dovrebbe essere risolto nella maggior parte dei compilatori ora.
Ci possono anche essere differenze nella velocità di compilazione tra enum e statici.

Ci sono alcuni dettagli nelle linee guida sulla codifica di boost e un thread più vecchio negli archivi boost riguardo al sobject.

Per alcuni il primo potrebbe sembrare meno di un hack e più naturale. Inoltre ha memoria allocata per se stessa se si utilizza la class, quindi è ansible ad esempio prendere l’indirizzo di val.

Quest’ultimo è meglio supportato da alcuni compilatori più vecchi.

Dall’altro lato della risposta di @Georg , quando una struttura che contiene una variabile const statica è definita in un modello specializzato, deve essere dichiarata nella sorgente in modo che il linker possa trovarla e dargli effettivamente un indirizzo a cui fare riferimento . Ciò potrebbe non essere necessario (a seconda degli effetti desiderati) causa codice inelegante, specialmente se si sta tentando di creare una libreria di sola intestazione. Potresti risolverlo convertendo i valori in funzioni che restituiscono il valore, che potrebbe aprire anche i modelli alle informazioni di runtime.