Conditional inclusion in C ++ 11 with a user-defined literal?

In C ++ 11, when the form preprocessor directive ...

#if expr 

..., expr is evaluated as constant-expression , as described in 16.1 [cpp.cond] .

This is done after replacing the macro with expr , its identifiers (and keywords) are replaced with 0, its preprocessing-tokens converted to tokens , the defined operator is evaluated, and so on.

My question is what happens when one of the tokens in expr is user-defined-literal ?

Custom literals are similar to function calls, but function calls cannot occur in expr (I think), as a side effect of identifier replacement. However, technically user-defined-literals can survive.

I suspect this is a mistake, but I cannot figure out how to conclude that from the standard?

Perhaps the (pedantic) effect of adding custom literals to section 16 [cpp] was simply ignored?

Or am I missing something?

Update:

To illustrate with an example:

What is this preprocess:

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

bar or baz or is it a mistake?

GCC 4.7 reports:

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

therefore, he believes that this is a mistake. Could this be justified with reference to the standard? Or is it just "implicit"?

+6
source share
2 answers

In C ++ 11, when a form preprocessing directive is encountered ... #if expr ... expr is evaluated as constant-expression , as described in 16.1 [cpp.cond] .

This is done after replacing the macro with expr , its identifiers (and keywords) are replaced with 0 , its preprocessing-tokens converted to tokens , the defined operator is evaluated, etc.

My question is what happens when one of the tokens in expr is user-defined-literal ?

The program is poorly formed.

The kernel of my argument is drawn from the observation in 16.1/1 footnote 147 that there are no identifiers in the translation phase 4, except for the names of the macros.

Argument:

According to 2.14.8 [lex.ext]/2

A user-defined-literal treated as a call to a literal operator or literal operator template (13.5.8) .

So, here we have the remaining function (operator) call even after all the replacements described in 16.1/4 . (Other attempts, such as using the constexpr function, would be thwarted by replacing all non-macro identifiers with 0 )

Since this occurs in phase 4 of the translation, there are no specific or even declared functions; an attempt to search for literal-operator-id should fail (see footnote 147 in 16.1/1 for a similar argument).

From a slightly different angle, looking at 5.19/2 , we find:

A conditional-expression is a core constant expression if it only includes one of the following as a potentially evaluated subexpression (3.2) [...]:

  • [...]
  • calling a function other than the constexpr constructor for a literal class or constexpr function;
  • calling the undefined function constexpr or the constructor undefined constexpr [...];

Because of this, using a user-defined literal in a constant expression requires a specific and constexpr literal operator , which again cannot be available in translation phase 4.

gcc has the right to reject this.

+3
source

In C ++ 11, when a preprocessing directive of the form #ifdef expr , expr is evaluated as a constant expression, as described in 16.1. This is done after replacing the macro with expr, its identifiers (and keywords) are replaced with 0, its pre-processing tokens are converted to tokens, a certain operator is defined, etc.

No!

The argument #ifdef , #ifndef or defined not evaluated. For example, suppose I never #define the preprocessor symbol SYMBOL_THAT_IS_NEVER_DEFINED . This is absolutely true:

 #ifdef SYMBOL_THAT_IS_NEVER_DEFINED code #endif 

Extending a character that is not defined is illegal. This is illegal if SYMBOL_THAT_IS_NEVER_DEFINED not defined:

 #if SYMBOL_THAT_IS_NEVER_DEFINED code #endif 

Similar to checking whether a pointer is non-null before dereferencing it, checking that the symbol is correctly defined before using it is legal:

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

All Articles