In C++11 when a preprocessing directive of the form...
#if expr
...is encountered,expr
is evaluated as a constant-expression
as described in 16.1 [cpp.cond]
.
This is done after macro replacement on expr
, its identifiers (and keywords) are replaced by 0, its preprocessing-tokens
are converted to tokens
, defined
operator is evaluated, and so on.
My question is what happens when one of the tokens in expr
is a user-defined-literal
?
User defined literals are like function calls, but function calls can't occur in expr
(I think), as a side effect of the identifier replacement. However technically user-defined-literals
could survive.
I suspect it is an error, but I can't quite see how to conclude that from the standard?
Perhaps the (pedantic) impact of adding user defined literals on clause 16 [cpp]
was simply ignored?
Or am I missing something?
Update:
To clarify by an example:
What does this preprocess to:
#if 123_foo + 5.5 > 100
bar
#else
baz
#endif
bar or baz or is it an error?
GCC 4.7 reports:
test.cpp:1:5: error: user-defined literal in preprocessor expression
so it thinks it is an error. Can this be justified with reference to the standard? Or is this just "implicit"?
In C++11 when a preprocessing directive of the form...
#if expr ...
is encountered,expr
is evaluated as aconstant-expression
as described in16.1 [cpp.cond]
.This is done after macro replacement on
expr
, its identifiers (and keywords) are replaced by0
, itspreprocessing-tokens
are converted totokens
,defined
operator is evaluated, and so on.My question is what happens when one of the
tokens
inexpr
is auser-defined-literal
?
The program is ill-formed.
The core of my argument is gleaned from the observation in 16.1/1
footnote 147
, that in translation phase 4 there are no identifiers
other than macro names yet.
Argument:
According to 2.14.8 [lex.ext]/2
A
user-defined-literal
is treated as a call to aliteral operator
orliteral operator template
(13.5.8)
.
So here we have a remaining call to an (operator) function even after all the substitutions described in 16.1/4
. (Other attempts, for example to use a constexpr
function, would be thwarted by the substitution of all non-macro identifiers
by 0
.)
As this occurs in translation phase 4, there are no defined or even declared functions yet; an attempted lookup of the literal-operator-id
must 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 acore constant expression
unless it involves one of the following as a potentially evaluated subexpression (3.2) [...]:
- [...]
- an invocation of a function other than a constexpr constructor for a literal class or a constexpr function;
- an invocation of an undefined constexpr function or an undefined constexpr constructor [...];
From this, use of a user-defined literal
in a constant expression
requires a defined and constexpr literal operator
, which again can't be available in translation phase 4.
gcc is right to reject this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With