19

For example:

constexpr int g() { return 30; }    

constexpr int f()
{
    // Can we omit const?
    const int x = g();
    const int y = 10;

    return x + y;
}

Is there any point to ever declare local variables in a constexpr function with const?

Aren't constexpr functions with const local variables equivalent to those with no const?

In other words, does constexpr on a function impose (imply) const on its local variables?

Leo Heinsaar
  • 3,887
  • 3
  • 15
  • 35
  • 12
    I disagree with your premise that omitting `const` makes a function look "cleaner". Also, no, I don't think so. But I'm no `constexpr`t. – Lightness Races in Orbit Nov 01 '15 at 15:29
  • 4
    You can even [change them](http://ideone.com/L4Oa68)! (And its logical, it does not make function _not pure_) – Lol4t0 Nov 01 '15 at 15:31
  • 2
    @LeoHeinsaar I think you mean less non-whitespace characters, because otherwise it can be trivially made 'cleaner' by that definition in a way that will almost universally be interpreted as unreadable. –  Nov 01 '15 at 15:34
  • 2
    @LeoHeinsaar so you think obfuscated C++ is cleaner because it has fewer characters? – stark Nov 01 '15 at 15:35
  • Here is the cleanest: `constexpr int f(){int x=g(),y=10;return x+y;}` (seriously) – edc65 Nov 01 '15 at 19:15
  • "In other words, does `constexpr` on a function **impose** (imply) `const` on its local variables?" No. As would have been clear from writing some simple code to test that question. Modifiable variables in `constexpr` functions are an extremely important part of their usefulness. – underscore_d May 12 '17 at 12:07

4 Answers4

23

The same arguments for declaring variables as const in non-constexpr functions also apply to constexpr functions:

  • Declaring a variable const documents the fact that it won't ever be changed. This may in some instances help make the function more readable.
  • Declaring a variable const affects overload resolution, and may make h(x) resolve h differently depending on whether x is const.

Of course, in the opposite direction, as mentioned in comments already:

Even in constexpr functions, local variables may be changed. If those variables are then changed so that they are const, attempts to change them will no longer be accepted.

  • I think this is a good answer. Without harder thought it may make an impression that `constexpr` on a function somehow imposes (implies) constness on everything inside it, including local variables (because, for example, you can't call a non-constexpr functions from it). Thanks. – Leo Heinsaar Nov 01 '15 at 17:38
  • 4
    Of course, const local variables cannot be moved from on return. I'm very wary of const for locals for this reason. – Sebastian Redl Nov 01 '15 at 20:16
17

In this particular example the local variables would be best declared constexpr, not const, because they can be computed at compile time:

constexpr int g() { return 30; }    

constexpr int f()
{
    constexpr int x = g();
    constexpr int y = 10;

    return x + y;
}

When f() is called at run time, without the constexpr on x and y, (with or without the const on x and y) you are giving the compiler the option to initialize x and y at run time instead of compile time. With the constexpr on x and y, the compiler shall compute x and y at compile time, even when f() is executed at run time.

In a different function however, constexpr can't always be used. For example if f() and g() took a parameter:

constexpr int g(int z) { return z+30; }    

constexpr int f(int z)
{
    const int x = g(z);
    constexpr int y = 10;

    return x + y;
}

Now x can not be marked constexpr because z may not be a compile-time constant, and there is currently no way to mark it as such. So in this case, marking x const is the best you can do.

Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
  • 1
    Would it be reasonable to require to imply `constexpr` on local variables that aren't changed? – Leo Heinsaar Nov 02 '15 at 09:34
  • @LeoHeinsaar: I'm afraid not. In this example, what if `g()` is not marked `constexpr`? In that case it's result `x` can not be marked `constexpr`, and the compiler is within its rights to compute `g()` at run time. Perhaps `g()` needs to make a phone call to get its result... – Howard Hinnant Nov 02 '15 at 14:51
  • Oh I see. That is revealing. Thanks Howard. – Leo Heinsaar Nov 02 '15 at 16:28
4

You not only can, but sometimes you must (i.e. if the variable changes), eg:

constexpr size_t f(size_t n) {
    size_t val = 1;
    if (n == 0) val++;
    return val;
}
char arr0[f(0)] = {'a', 'x'};
char arr1[f(1)] = {'y'};

is fine in C++14.

Paul Evans
  • 27,315
  • 3
  • 37
  • 54
1

In general, a function can't be evaluated at compile time and therefore can't be called in a constant expression. Specifying a function as constexpr indicates that it can be used in constant expressions IF its input arguments are constants. For example this...

constexpr int n = func(7);

... must be evaluated at compile time.

That's the meaning of constexpr before functions. This being the case, it doesn't follow that the local variables inside the function don't have to be specified const.

dspfnder
  • 1,135
  • 1
  • 8
  • 13