Constexpr

FAQ

  1. Why is there so much online chat about the C++ term constexpr?

    constexpr lets you run real C++ programs during compilation, not just when the program runs. By declaring functions as constexpr they are run at compile time, often to produce look-up tables that are blindingly fast to execute at runtime. For example:

    struct Entry
    {
        uint64_t hash;
        int id;
    };
    
    constexpr auto build_table()
    {
        std::array<Entry, words.size()> table{};
    
        for (size_t i = 0; i < words.size(); ++i)
        {
            table[i] = { hash_str(words[i]), static_cast<int>(i) };
        }
    
        // compile-time sort (yes, really)
        std::ranges::sort(table, {}, &Entry::hash);
    
        return table;
    }
    
    constexpr auto lookup_table = build_table();

    At runtime the binary will contain something like the following:

    constexpr Entry lookup_table[] = {
        {0x1234..., 0},
        {0x2af3..., 1},
        {0x88ab..., 2},
        ...
    };

    This means that at runtime there is no parsing, no hashing, no sorting, no allocations - just a table look-up. Simply, anything done at compile time costs zero runtime CPU. It’s one of the biggest long-term evolutions in the language.

  2. How does constexpr improve program safety?

    By using constexpr your program will often fail at compilation if something is wrong, and not at runtime. For example, invalid configuration, out-of-range values, bad lookup tables, and broken assumptions will often appear as compile time errors.

  3. How does constexpr compare with constevel?

    A constexpr function can run at compile-time, or can run at runtime. A consteval function must run at compile-time. consteval is perfect for compile-time string hashing, generating IDs, reflection helpers, and for building static lookup tables. constexpr is the more powerful as it gives you compile-time when possible, runtime when needed.

  4. What is the history of constexpr?

    A table shows the developing nature of this concept:

    Standard What changed

    C++11

    constexpr introduced (very limited)

    C++14

    Loops and more logic allowed

    C++17

    More library support

    C++20

    Dynamic allocation, containers, algorithms

    C++23

    Ever more library functions become constexpr

    C++26

    Huge expansion — reflection and "constexpr everywhere"

  5. What applications typically use the constexpr approach?

    Apps where performance is king: game engines, compilers, serialization libraries, networking protocols, embedded systems, to name a few.

  6. What Boost libraries take advantage of the power of constexpr?

    Over the last 5 to 10 years, many Boost libraries have been heavily modernized to exploit constexpr, it’s sibling consteval, and compile-time metaprogramming. A modern Boost-heavy project can parse URLs, generate serializers, build type-safe APIs, and compute math tables - all at compile time. For example:

    • Boost.Hana : The flagship constexpr metaprogramming library, built around compile-time computation, type-level programming, and constexpr containers and algorithms - such as filters, transforms, folds, sorts.

    • Boost.Mp11 : Ultra-fast constexpr template metaprogramming.

    • Boost.Describe : Provides constexpr reflection. You can iiterate fields at compile time, generate serializers, generate UI bindings, build ORM mapping, and auto-generate JSON - all via constexpr metadata.

    • Boost.Pfr : Provides constexpr reflection without macros, and iterate, serialize, and compare structs at compile time.

    • Boost.StaticString : Enables constexpr strings.

    • Boost.URL : Designed so some parsing can run at compile time.

    • Boost.Json : Uses constexpr for lookup tables, parsers, and optimized state machines.

    • Boost.Container : Steadily becoming more constexpr-capable.

    • Boost.Math : Huge portions now support compile-time evaluation of constants, special functions, numeric limits, and lookup tables.