2013-02-16 15 views
6

In C++ 11 quando viene rilevato un direttiva al preprocessore della forma ...Inclusione condizionale in C++ 11 con valori letterali definiti dall'utente?

#if expr 

..., expr è valutato come un constant-expression come descritto in 16.1 [cpp.cond].

Ciò avviene dopo macro sostituzione su expr, relativi identificatori (e le chiavi) sono sostituiti da 0, il suo preprocessing-tokens sono convertiti tokens, defined operatore viene valutata, e così via.

La mia domanda è cosa succede quando uno dei token in expr è un user-defined-literal?

I valori letterali definiti dall'utente sono come le chiamate di funzione, ma le chiamate di funzione non possono verificarsi in expr (credo), come effetto collaterale della sostituzione dell'identificatore. Tuttavia, tecnicamente user-defined-literals potrebbe sopravvivere.

Ho il sospetto che sia un errore, ma non riesco a capire come concludere quello standard?

Forse l'impatto (pedante) dell'aggiunta di valori letterali definiti dall'utente alla clausola 16 [cpp] è stato semplicemente ignorato?

O mi manca qualcosa?

Aggiornamento:

Per chiarire con un esempio:

Che cosa significa questo pre-elaborazione a:

#if 123_foo + 5.5 > 100 
bar 
#else 
baz 
#endif 

bar o baz o è un errore?

GCC 4.7 rapporti:

test.cpp:1:5: error: user-defined literal in preprocessor expression 

quindi pensa è un errore. Questo può essere giustificato con riferimento allo standard? O è solo "implicito"?

+0

La nozione di "espressione costante" del preprocessore è molto diversa da quella del C++, credo. Puoi davvero usare solo letterali e macro che alla fine si espandono in letterali ... almeno è così che ho sempre capito. –

+0

Sembra che la tua versione di g ++ manchi qualcosa, non tu. –

+1

Dubito che sia stato l'intento del comitato di consentire questo genere di cose, dal momento che la logica della preelaborazione e della semantica del linguaggio sono sempre state così separate. Ma sì, lo standard sembra implicare che dovrebbe essere gestito. – aschepler

risposta

3

in C++ 11 quando una direttiva al preprocessore della forma ... #if expr ... viene rilevato, expr è valutato come un constant-expression come descritto in 16.1 [cpp.cond].

Questo viene fatto dopo la sostituzione macro su expr, relativi identificatori (e le chiavi) sono sostituiti da 0, sua preprocessing-tokens sono convertiti tokens, defined operatore viene valutata, e così via.

La mia domanda è che cosa accade quando uno dei tokens in expr è una user-defined-literal?

Il programma è mal formato.

Il nucleo della mia argomentazione viene estratta dalla constatazione in 16.1/1 nota 147, che nella fase di traduzione 4 non ci sono identifiers altro che nomi di macro ancora.

Argomento:

Secondo 2.14.8 [lex.ext]/2

Un user-defined-literal viene trattata come una chiamata a un literal operator o literal operator template(13.5.8).

Quindi qui abbiamo una chiamata rimanente a una funzione (operatore) anche dopo tutte le sostituzioni descritte in 16.1/4. (Altri tentativi, ad esempio per utilizzare una funzione constexpr, verrebbe vanificata dalla sostituzione di tutti i non-macro identifiers da 0.)

Come questo avviene in fase di traduzione 4, ci sono presenti funzioni definite o addirittura dichiarati ancora; una tentata ricerca di literal-operator-id deve fallire (vedere la nota 147 in 16.1/1 per un argomento simile).

Da un angolo leggermente diverso, guardando 5.19/2 troviamo:

Un conditional-expression è un core constant expression a meno che non comporta una delle seguenti come sottoespressione potenzialmente valutato (3,2) [...]:

  • [...]
  • un'invocazione di una funzione diversa da un costruttore di constexpr per una classe letterale o una funzione constexpr;
  • un'invocazione di una funzione constexpr non definita o un costruttore di constexpr non definito [...];

Da questo, l'uso di un user-defined literal in una constant expression richiede una definito e constexprliteral operator, che ancora una volta non può essere disponibile in fase di traduzione 4.

gcc è diritto di respingere Questo.

0

In C++ 11 quando viene rilevato un direttiva al preprocessore della forma #ifdef expr, expr è valutato come una costante espressione come descritto 16.1. Questo viene fatto dopo la sostituzione di macro su expr, i suoi identificatori (e parole chiave) sono sostituiti da 0, i token di preelaborazione vengono convertiti in token, l'operatore definito viene valutato e così via.

No!

L'argomento di #ifdef, #ifndef, o defined è non valutata. Ad esempio, supponiamo di non avere mai il simbolo del preprocessore SYMBOL_THAT_IS_NEVER_DEFINED. Questo è perfettamente valido:

#ifdef SYMBOL_THAT_IS_NEVER_DEFINED 
code 
#endif 

L'espansione di un simbolo che il simbolo non è definito è illegale.Questo è illegale assumendo SYMBOL_THAT_IS_NEVER_DEFINED non è stato definito:

#if SYMBOL_THAT_IS_NEVER_DEFINED 
code 
#endif 

Analogamente a verificare se un puntatore è nullo prima deferenziandolo, verificando se un simbolo è definito prima di usarlo è legale:

#if (defined SYMBOL_THAT_MIGHT_BE_DEFINED) && SYMBOL_THAT_MIGHT_BE_DEFINED 
code 
#endif 
+0

Mi spiace di aver fatto un refuso nella domanda, intendevo '#if expr', non' #ifdef expr'. Ho corretto la domanda, per favore aggiusta la risposta in modo appropriato. –

+0

Si noti inoltre che 'espr nella mia domanda rappresenta un'intera serie di token che corrispondono a 'espressione costante' - e non il singolo identificativo' expr'. –

+0

Vedere "Aggiornamento" nella domanda –

Problemi correlati