10

I'm studying the C++ programming language and in a chapter my book introduces me the concept of constant :

A constexpr symbolic constant must be given a value that is known at compile time

What is a value known at compile time ? Why are we in need of them ?

AthulMuralidhar
  • 662
  • 1
  • 9
  • 26
piero borrelli
  • 737
  • 2
  • 9
  • 20
  • 3
    for example: `int x = 3.0f;`, the value of `x` is known at compile time. – Borgleader Nov 03 '14 at 18:55
  • 4
    The definition is misleading - a constexpr (in C++ 11) is a value or function, which can be evaluated at compile time. –  Nov 03 '14 at 18:58
  • Related to [“Constant expressions” prior to C++11](http://stackoverflow.com/q/26024942/170880) ... there is a lot of ground-work in my answer that may be helpful. What defines a constant expression is hard to define in a simple way. – Shafik Yaghmour Nov 03 '14 at 19:04

3 Answers3

6

A constant expression means an expression that can be evaluated at compile-time (i.e. before the program runs, during compilation) by the compiler.

A constant expression can be used to initialize a variable marked with constexpr (referring to the C++11 concept). Such a variable gives the compiler the hint that it could be compile-time evaluated (and that might spare precious runtime cycles), e.g.

#include <iostream>

constexpr int factorial(int n) // Everything here is known at compile time
{
    return n <= 1 ? 1 : (n * factorial(n - 1));
}

int main(void)
{
    constexpr int f = factorial(4); // 4 is also known at compile time
    std::cout << f << std::endl;
    return 0;
}

Example

If you don't provide a constant expression, there's no way the compiler can actually do all this job at compile-time:

#include <iostream>

constexpr int factorial(int n) // Everything here is known at compile time
{
    return n <= 1 ? 1 : (n * factorial(n - 1));
}

int main(void)
{
    int i;
    std::cin >> i;
    const int f = factorial(i); // I really can't guess this at compile time..
                                // thus it can't be marked with constexpr
    std::cout << f << std::endl;
    return 0;
}

Example

The gain in doing compile-time extra-work instead of run-time work is performance gain since your compiled program might be able to use precomputed values instead of having to compute them from scratch each time. The more expensive the constant expression is, the bigger is the gain your program gets.

Marco A.
  • 43,032
  • 26
  • 132
  • 246
  • @pieroborrelli you need to study C++ better, I didn't write complex stuff. In simple words: if you need a function that calculates something and you know that it could be done at compile time instead of run time, C++ can help you do it and pre-compute that function's value. Having the result immediately during compilation is more efficient than having to calculate it when the program is running. **I can't explain it simpler than this** – Marco A. Nov 04 '14 at 17:28
  • @ Marco A. OK thank you, just one question : when I use a variable initialized without the constexpr notation, is that variable created in memory at run time ? – piero borrelli Nov 05 '14 at 16:33
  • @pieroborrelli It depends on the storage type of the variable (e.g. static, automatic, etc..) but it can't appear in a constexpr expression. – Marco A. Nov 05 '14 at 16:36
5

What is a value known at compile time ?

I think it makes more sense to talk about constant expressions. A constant expression has a value that is known at compile time. Roughly speaking, it may be simply a literal, the name of another variable (whose value again is known at compile time) or a complex expression involving sub-expressions with values known at compile time.

The quote states that the initializer of a variable declared with constexpr needs to be a constant expression. In particular there are requirements an expression must satisfy to be a constant expression; Those are listed here.

Examples are

constexpr int i = 54;
constexpr float f = 684; // Compile-time conversion from int to float

constexpr int func( int i )
{
    return i*47 % 23;
}

constexpr auto value = func(i * f); // Okay; constexpr function called
                                    // with arguments that, when substituted inside,
                                    // yield constant expressions

Sometimes a value is actually known at compile time but the expression isn't a constant one according to standard. That includes

int i = 43;
constexpr int j = reinterpret_cast<int>(i); // Shouldn't compile. (Does with GCC)

There are cases were the compiler may do constant folding - some values can be computed at compile time but don't have to be.

int i = 0;

for (int j = 1; j != 10; ++j)
    i += j;

return i;

The compiler can completely eliminate the loop and initialize i with 55 (or simply return 55 and eliminate i too) as long as the behavior stays the same. This is known as the as-if rule.

Columbo
  • 60,038
  • 8
  • 155
  • 203
  • In that case make either a defect report to the compiler or the standard [isocpp](https://isocpp.org/). – Surt Nov 03 '14 at 19:09
  • @Surt I think the developers of GCC are well aware of this. – Columbo Nov 03 '14 at 19:10
  • I was thinking that is should compile, since it ultimately evaluates to i and if `constexpr int j = i;` is OK so should the expression you've made also be. – Surt Nov 03 '14 at 19:14
  • @Surt According to [expr.const] an expression is a constant expression unless it involves a `reinterpret_cast`. This is to prevent type-punning or such at compile-time. – Columbo Nov 03 '14 at 19:16
  • Hmmm, I knew they allowed [__builtin_constant_p](http://stackoverflow.com/a/24400015/1708801) I am a bit surprised they allow a raw `reinterpret_cast`. I am getting an error when I try that, what version, can you provide a live example? – Shafik Yaghmour Nov 03 '14 at 19:18
  • @Columbo sorry I can't undersand your example because I started to study C++ just one months ago. Can you answer me using just words for absolutely beginner ? Is a variable a constant expression ? What is the difference between a variable and a constexpr variable when i compile the program ? – piero borrelli Nov 04 '14 at 17:25
3

It means that the program doesn't need to run in order to compute the constant. For example:

int num = 4;

You need these values in order for the compiler to place the variables in symbol tables, where they can be referenced by the program and used. In the case of constants, the compiler symbolizes constants as values that cannot be changed. So if you declare a constant as something that is determined at run-time, it will not work, because if a constant is undefined at compile-time it stays undefined. I hope this makes sense.

Lawrence Aiello
  • 4,560
  • 5
  • 21
  • 35