constexpr names a value that can be used at compile time, while ordinary variables still drive runtime decisions.

constexpr A `constexpr` variable is known during compilation when its initializer is also a constant expression.

Constexpr Config

used
constexpr_config.cpp
Replay: real traced execution (multi-file project)
#include <array>
#include <iostream>

int main() {
    constexpr int freeLimit = 3;
    int used = 2;

    std::array<int, freeLimit> included{1, 2, 3};
    bool overLimit = used > freeLimit;

    std::cout << "freeLimit=" << freeLimit << std::endl;
    std::cout << "includedSlots=" << included.size() << std::endl;
    std::cout << "used=" << used << std::endl;
    std::cout << "overLimit=" << overLimit << std::endl;
    return 0;
}
#include <array>
#include <iostream>

int main() {
    constexpr int freeLimit = 3;
    int used = 1;

    std::array<int, freeLimit> included{1, 2, 3};
    bool overLimit = used > freeLimit;

    std::cout << "freeLimit=" << freeLimit << std::endl;
    std::cout << "includedSlots=" << included.size() << std::endl;
    std::cout << "used=" << used << std::endl;
    std::cout << "overLimit=" << overLimit << std::endl;
    return 0;
}
#include <array>
#include <iostream>

int main() {
    constexpr int freeLimit = 3;
    int used = 4;

    std::array<int, freeLimit> included{1, 2, 3};
    bool overLimit = used > freeLimit;

    std::cout << "freeLimit=" << freeLimit << std::endl;
    std::cout << "includedSlots=" << included.size() << std::endl;
    std::cout << "used=" << used << std::endl;
    std::cout << "overLimit=" << overLimit << std::endl;
    return 0;
}
  1. freeLimit ← 3, used ← 2, included ← (empty), overLimit ← 0

    4int main() {5    constexpr int freeLimit→ 3 = 3;6    int used→ 2 = 2; //@used=1, 478    std::array<int, freeLimit> included→ (empty){1, 2, 3};9    bool overLimit→ 0 = used2 > freeLimit3;1011    std::cout << "freeLimit=" << freeLimit3 << std::endl;12    std::cout << "includedSlots=" << included(empty).size() << std::endl;13    std::cout << "used=" << used2 << std::endl;14    std::cout << "overLimit=" << overLimit0 << std::endl;15    return 0;16}
    outputfreeLimit=3
    includedSlots=3
    used=2
    overLimit=0
  1. freeLimit ← 3, used ← 1, included ← (empty), overLimit ← 0

    4int main() {5    constexpr int freeLimit→ 3 = 3;6    int used→ 1 = 1;78    std::array<int, freeLimit> included→ (empty){1, 2, 3};9    bool overLimit→ 0 = used1 > freeLimit3;1011    std::cout << "freeLimit=" << freeLimit3 << std::endl;12    std::cout << "includedSlots=" << included(empty).size() << std::endl;13    std::cout << "used=" << used1 << std::endl;14    std::cout << "overLimit=" << overLimit0 << std::endl;15    return 0;16}
    outputfreeLimit=3
    includedSlots=3
    used=1
    overLimit=0
  1. freeLimit ← 3, used ← 4, included ← (empty), overLimit ← 1

    4int main() {5    constexpr int freeLimit→ 3 = 3;6    int used→ 4 = 4;78    std::array<int, freeLimit> included→ (empty){1, 2, 3};9    bool overLimit→ 1 = used4 > freeLimit3;1011    std::cout << "freeLimit=" << freeLimit3 << std::endl;12    std::cout << "includedSlots=" << included(empty).size() << std::endl;13    std::cout << "used=" << used4 << std::endl;14    std::cout << "overLimit=" << overLimit1 << std::endl;15    return 0;16}
    outputfreeLimit=3
    includedSlots=3
    used=4
    overLimit=1

Follow the Config

  1. freeLimit is 3, and the array uses that value for its size.
  2. included has three slots: 1, 2, and 3.
  3. used starts at 2.
  4. overLimit checks whether used > freeLimit.
  5. With 2 > 3 false, the program prints overLimit=0. | used | freeLimit | includedSlots | overLimit output | | ---: | ---: | ---: | --- | | 1 | 3 | 3 | overLimit=0 | | 2 | 3 | 3 | overLimit=0 | | 4 | 3 | 3 | overLimit=1 |

Exercise: constexpr_config.cpp

Reproduce freeLimit=3, includedSlots=3, used=2, and overLimit=0, then use used 1 and 4 to predict the overLimit line.