2009-03-13 30 views
8

Se si utilizza un modello in C++ che accetta un valore intero come parametro, esistono dei requisiti su una variabile intera utilizzata come parametro diverso rispetto a quando la variabile è stata utilizzata come parametro in una chiamata di funzione?Quali sono i requisiti per i parametri del modello C++?

Questo è un seguito alla domanda here. Voglio specificatamente indicare se esiste una differenza tra le variabili WRT dichiarate come "extern const int" per funzioni o modelli?

Posso vedere che per alcuni casi di template il valore del parametro sarebbe necessario al momento della compilazione. È sempre vero? C'è un modo per specificare, forse solo per determinati usi del valore del parametro, che il valore deve essere usato in fase di runtime?

risposta

3

È sempre il caso che il valore di int sia necessario al momento della compilazione.

Poiché ogni modello di istanziazione è un pezzo separato di codice compilato (anche per i modelli di modelli interi) che deve essere disponibile per intero quando viene compilato (e deve essere garantito che non cambi mai).

Questo è anche il motivo per cui è una buona idea non utilizzare i parametri dei modelli interi quando si utilizzerà un numero elevato di valori univoci: è possibile finire rapidamente con un file eseguibile enorme.

13

Quanto segue è dallo standard.

14.3.2.1:

Un modello-argomento per un non-tipo, non-template-parametro deve essere:

  • un integrale costante espressione di integrale o censimento genere; oppure
  • il nome di un parametro di modello non di tipo; oppure
  • l'indirizzo di un oggetto o funzione con collegamento esterno, inclusi modelli di funzione e id modello di funzione, esclusi i membri di classe non statici, espresso come & id-expression dove lo & è facoltativo se il nome fa riferimento a una funzione o array, o se il parametro template corrispondente è un riferimento; oppure
  • un puntatore al membro espresso come descritto in 5.3.1.

5.19.1:

In diversi luoghi, C++ richiede espressioni che restituiscono un costante integrale o censimento: come limiti di matrice (8.3.4, 5.3.4), come espressioni case (6.4.2), come lunghezza dei campi di bit (9.6), come inizializzatori di enumeratori (7.2), come inizializzatori di membri statici (9.4.2) e come argomenti di modelli non di tipo integrale o di enumerazione (14.3).

constant-expression: 
      conditional-expression 

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 di tipo parametri di modello di integrale o censimento tipi e dimensioni delle espressioni. I letterali mobili (2.13.3) possono apparire solo se sono convertiti in tipi interi o di enumerazione. È possibile utilizzare solo tipi di conversioni di tipo integrale o enumera- .In particolare, ad eccezione delle dimensioni delle espressioni, le funzioni, gli oggetti di classe, i puntatori o i riferimenti non devono essere utilizzati e gli operatori di assegnazione, incremento, decremento, chiamata di funzione o virgola non devono essere utilizzati.

Rispetto al tuo post precedente credo l'essenza nella parte "variabili const ... inizializzato con ..." (e non credo inizializzati esternamente conta).

4

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).

Problemi correlati