Consider the following code:
#include <stdio.h>
constexpr int f()
{
return printf("a side effect!\n");
}
int main()
{
char a[f()];
printf("%zd\n", sizeof a);
}
I would have expected the compiler to complain about the call to printf
inside f
, because f
is supposed to be constexpr
, but printf
is not. Why does the program compile and print 15?
A call to a constexpr function produces the same result as a call to an equivalent non- constexpr function , except that a call to a constexpr function can appear in a constant expression. The main function cannot be declared with the constexpr specifier.
Even though try blocks and inline assembly are allowed in constexpr functions, throwing exceptions or executing the assembly is still disallowed in a constant expression.
A static constexpr variable has to be set at compilation, because its lifetime is the the whole program. Without the static keyword, the compiler isn't bound to set the value at compilation, and could decide to set it later.
Constexpr functions are implicitly inline, which means they are suitable to be defined in header files. Like any function in a header, the compiler is more likely to inline it than other functions.
The program is ill-formed and requires no diagnostic according to the C++11 draft standard section 7.1.5
The constexpr specifier paragraph 5 which says:
For a constexpr function, if no function argument values exist such that the function invocation substitution would produce a constant expression (5.19), the program is ill-formed; no diagnostic required.
and provides the following example:
constexpr int f(bool b)
{ return b ? throw 0 : 0; } // OK
constexpr int f() { return f(true); } // ill-formed, no diagnostic required
and section 5.19
paragraph 2 says:
A conditional-expression is a core constant expression unless it involves one of the following as a potentially evaluated subexpression [...]
and includes:
— an invocation of a function other than a constexpr constructor for a literal class or a constexpr function [ Note: Overload resolution (13.3) is applied as usual —end note ];
We would probably prefer a diagnostic in this case, it could just be an oversight, I have a bug report for a similar situation where gcc
does not produce an error but we would probably like it to: Is the compiler allowed leeway in what it considers undefined behavior in a constant expression?.
Update
Using the -fno-builtin
flag will cause gcc
to generate the following error:
error: call to non-constexpr function 'int printf(const char*, ...)'
return printf("a side effect!\n");
^
So gcc
does consider this ill-formed it is just ignores it when it is using the builtin version of printf
.
Although somewhat inconsistently using the -pedantic
produces the following warning:
warning: ISO C++ forbids variable length array 'a' [-Wvla]
char a[f()];
^
Note that using f()
to initialized a constexpr variable:
constexpr int x = f() ;
does generate an error:
error: 'printf(((const char*)"a side effect!\012"))' is not a constant expression
Note that additionally in the more general case a compiler is not allowed mark standard library functions as constexpr unless explicitly allowed by the standard.
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