Deve essere un'espressione costante integrata. Questo è spiegato dal documento standard a 5.19
:
Un integrale costante espressione può coinvolgere solo letterali (2,13), enumeratori, variabili const o membri dati statici di tipi integrali o enumerazione inizializzate con espressioni costanti (8.5), non -tipo parametri del template di tipi interi o di enumerazione e sizeof espressioni. I letterali mobili (2.13.3) possono apparire solo se sono convertiti in tipi interi o di enumerazione. È possibile utilizzare solo conversioni di tipo integrale o di enumerazione.
Si noti che "integrale" è un altro termine per "intero", ma non è uguale a "int". "char" ad esempio ha il tipo intero/integrale, ma non è il tipo int, ovviamente. Quindi in concreto, il seguente è consentito
10 or 10L or anything like that
enum { THIS, OR, THAT };
int const this_one = 10;
sizeof(char)
- naturalmente, qualsiasi altro parametro di modello come sopra
Una di queste può essere usato come argomento modello per un parametro che ha un tipo intero di th e il tipo corrispondente Alcune conversioni sono ancora applicate però. Quindi se vuole un int e tu passi un char, automaticamente promuove il char per l'int. Lo stesso se fornisci un enumeratore e vuole un int.
Così da tali norme, se avete
extern const int SomeName;
E non vede una definizione che inizializza che costante con un integrale un'espressione costante, non può essere usato come un argomento di template. Ma può essere usato come argomento di funzione, ovviamente. Questi non hanno bisogno di essere conosciuti al momento della compilazione perché quelli non fanno parte di un tipo. Nel momento in cui è il nome di un modello di specializzazione, gli argomenti si utilizzati a far parte del tipo:
MyGreatStack<int, 4> // 4 is now part of the type MyGreatStack<int, 4>!
Si noti che ci sono altri modi per passare SomeName
come argomento. Tuttavia, tutti possono non essere accettati da un parametro di modello intero. È possibile accettare quanto sopra da un parametro di riferimento, ad esempio
template<const int& V> struct NowItWorks { };
e sarebbe accettare la SomeName
di sopra. Ora, piuttosto che un valore, è stata scelta una posizione particolare che è unica nell'intero programma (come la variabile ha il collegamento extern
).