AlwaysLearning
AlwaysLearning

Reputation: 8051

Can a constexpr function call a function that returns void?

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

Answers (2)

5gon12eder
5gon12eder

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

Mark B
Mark B

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

Related Questions