Reputation: 8051
This is what I would like to do:
void g() {
std::cout << "smth1" << std::endl;
std::cout << "smth2" << std::endl;
}
constexpr bool f() {return g(), true;}
The compiler (gcc
version 4.8.2) is not happy with this, since g
is not constexpr
. Is it possible to get around this problem?
Upvotes: 1
Views: 1470
Reputation: 25449
Any evaluation of a function called during the evaluation of a constant expression must not have any side effects. In C++11, the rules are actually much stricter, allowing only a single return
statement as function body but that's not relevant to this question.
The compiler is not entitled to remove any code from a constexpr
function in order to make it comply. It is your responsibility to not write such code in the first place.
However, it is okay to have code with side effects inside a constexpr
function if the control flow during static evaluation never passes through it.
This is valid C++11.
void g() { std::cout << "hello, world" << std::endl; }
constexpr bool f(const bool p = false) { return p ? (g(), false) : true; }
And you may call f
like this.
constexpr auto x = f(); // ok
Because p
is false
at compile-time, the compiler need not evaluate the call to g
. At run-time, you may call f
with either argument just as if it were not a constexpr
function.
f(false); // ok
f(true); // ok, produces output at run-time
What you cannot do is evaluate it in a constant expression with the parameter set to true
.
constexpr auto x = f(true); // compile-time error
Of course, this example is contrived beyond any restrictions and you should simply write
constexpr bool f() noexcept { return true; }
or use a variable
constexpr auto toggle = true;
if this is all you need.
Upvotes: 1
Reputation: 96291
The point of constexpr is that it can be fully expanded at compile-time. There is no possible way that the compiler can put runtime side effects (using cout
) into what is effectively a more complex compile-time constant. Put another way: No actual function call will be made at runtime for constexpr
functions!
Luckily the solution is easy!
Change f
to constexpr bool f() { return true;}
and your conditional to:
g();
if(f())
{
// ...
}
Upvotes: 4