Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nesting contexpr functions error

Tags:

c++

constexpr

The follwing code doesn't compile with g++/clang++.

constexpr int bar(int v) {
    if (v > 0){
        return v * 2;
    }
    return 2;
}

constexpr int foo(const int v) {
    constexpr auto x =  bar(v); // error
    return v;
}

int main() {
    constexpr auto a = foo(1);
    constexpr auto b = bar(1); // ok
}

The error message is: x must be initailized by a constant expression

But from the line (ok) you see that bar() is constexpr.

if I change the body of foo() to

constexpr int foo(const int v) {
    return bar(v);
}

its ok!

I don't get this clear, why the first form isn't possilble. I used g++-6.2.1, g++-7.0.0 and clang++-3.9.0

like image 734
wimalopaan Avatar asked Nov 19 '16 07:11

wimalopaan


People also ask

Should constexpr always be static?

The short answer is that not only is static useful, it is pretty well always going to be desired. First, note that static and constexpr are completely independent of each other. static defines the object's lifetime during execution; constexpr specifies that the object should be available during compilation.

Is constexpr guaranteed?

A constexpr function that is eligible to be evaluated at compile-time will only be evaluated at compile-time if the return value is used where a constant expression is required. Otherwise, compile-time evaluation is not guaranteed.

When to use #define vs constexpr?

#define directives create macro substitution, while constexpr variables are special type of variables. They literally have nothing in common beside the fact that before constexpr (or even const ) variables were available, macros were sometimes used when currently constexpr variable can be used.


1 Answers

The fix is this

constexpr int foo(const int v) {
    auto x =  bar(v);
    return v;
}

The keyword constexpr means two very slightly different things. A constexpr variable must be evaluated at compile time, whereas a constexpr function must be possible to evaluate at compile time. There is nothing to prevent you from calling foo at runtime. This means...

  1. The argument v is not necessarily constexpr.
  2. When bar is called with b the answer might not be constexpr.
  3. The result of cannot be stored in a constexpr variable as it might not be constexpr.

If foo is called at compile time then x is not stored, it is a temporary variable within the compiler, so making it constexpr doesn't make any sense.

The constexpr'ness of x can only make sense if foo is evaluated at runtime, in which case it cannot be constexpr, which cases an error.

like image 130
Tim Avatar answered Oct 04 '22 16:10

Tim