Coming from that question: How to build a custom macro that behaves differently when used as constexpr (like assert)?
I wonder why it is possible to call a non constexpr function if it is conditional.
void bla( )
{
std::cout << "bla called!" << std::endl;
}
constexpr bool check(bool condition)
{
//bla(); // can not directly be called -> not constexpr!
condition ? void (0) : bla(); // compiles and runs even if condition is true or false!
// if condition is const, it did not compile because it
// directly force execution of non constexpr function
true ? void(0): bla(); // also that compiles!, ok, directly evaluated
//true ? bla(): void(0); // that did not compile;)
//false ? void(0): bla(); // that did not compile;)
false ? bla(): void(0); // compiles, ok, directly evaluated
return 0;
}
int main()
{
check( false );
check( true );
}
Can someone explain which rules are given from the standard? As commented from W.F.: If result is used in constexpr term like an template parameter, it fails if condition results in evaluation of non constexpr function.
That makes assert
to complain directly while compiling if result is
used in constexpr term.
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 constexpr function is a function that can be invoked within a constant expression. A constexpr function must satisfy the following conditions: It is not virtual. Its return type is a literal type. Each of its parameters must be of a literal type.
constexpr indicates that the value, or return value, is constant and, where possible, is computed at compile time. A constexpr integral value can be used wherever a const integer is required, such as in template arguments and array declarations.
A constexpr
function implies that it is possible to evaluate the value of the function at compile time. Since this is possible for the input true
the function is a valid constexpr
. Remember that a constexpr
function can have an address just as a regular function, it does not need to be compile time, only when used as a compile time function (which you do not in your example).
As mentioned on the constexpr
page on cppreference:
A constexpr function must satisfy the following requirements:
- it must not be virtual
- its return type must be LiteralType
- each of its parameters must be LiteralType
- there exists at least one set of argument values such that an invocation of the function could be an evaluated subexpression of a core constant expression (for constructors, use in a constant initializer is sufficient) (since C++14). No diagnostic is required for a violation of this bullet. (Emphasis mine)
Your function fulfils all of the above requirements: it is not virtual, it returns a literal type, the parameter is literal. And more interestingly last bullet point: there exists at least one set of argument values for which the function is actually fully compile time. (hence my emphasis of the last bullet)
As W.F. mentioned in the comments, the function can be used compile time, but only for valid inputs, that is, inputs that does not lead to a sub expression that is not compile time constant. So the input true
will work, but false
will not since it will lead to bla
being evaluated.
This is also stated in the standard: §10.1.5.5:
For a constexpr function or constexpr constructor that is neither defaulted nor a template, if no argument values exist such that an invocation of the function or constructor could be an evaluated subexpression of a core constant expression (8.20), or, for a constructor, a constant initializer for some object (6.6.2), the program is ill-formed, no diagnostic required.
constexpr int f(bool b) { return b ? throw 0 : 0; } // OK constexpr int f() { return f(true); } // ill-formed, no diagnostic required
See the examples from the standard document in particular.
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