# auto, decltype, constexpr and Compile-Time Programming — C++

Source: https://www.skillbyai.com/en/cpp/t-compile-time

> Use type deduction and compile-time evaluation effectively.

## Letting the compiler do the work

Modern C++ moves more work to the compiler. **`auto`** deduces variable types and, for functions, return types. **`decltype(expr)`** yields the type of an expression, useful in generic code. **`constexpr`** functions can be evaluated at compile time when their arguments are constants, and since C++20 they can use loops, local variables, `std::vector` and `std::string` inside the evaluation. **`consteval`** (C++20) functions **must** run at compile time, and **`constinit`** guarantees a variable is initialised at compile time. **`static_assert`** checks conditions during compilation. **`if constexpr`** discards branches that do not apply to the instantiated type. **Type traits** in `<type_traits>` (`std::is_integral_v<T>`, `std::remove_cvref_t<T>`) inspect and transform types. Together these enable lookup tables computed at build time, configuration checked at compile time and generic code without run-time overhead. Use them when they simplify code or catch errors early, not merely to be clever.

## Compile-time computation and checks

The table is computed by the compiler; static_assert verifies it.

```cpp
#include <array>
#include <cstddef>
#include <string>
#include <type_traits>

constexpr std::array<unsigned long long, 21> make_factorials() {
    std::array<unsigned long long, 21> f{};
    f[0] = 1;
    for (std::size_t i = 1; i < f.size(); ++i) f[i] = f[i - 1] * i;   // loops allowed in constexpr
    return f;
}

constexpr auto factorials = make_factorials();                // computed at compile time
static_assert(factorials[5] == 120);
static_assert(factorials[20] == 2'432'902'008'176'640'000ULL);

consteval int kib(int n) { return n * 1024; }               // must be compile-time
constexpr int buffer_size = kib(64);

template <typename T>
std::string describe(const T& value) {
    if constexpr (std::is_integral_v<T>)            return "integer " + std::to_string(value);
    else if constexpr (std::is_floating_point_v<T>) return "real " + std::to_string(value);
    else                                            return "something else";
}
```

## constexpr is permission, not a promise

A `constexpr` function can still run at run time when given run-time values. If evaluation must happen at compile time, use the result in a `constexpr` variable, a `static_assert`, or mark the function `consteval`.

**Quiz:** What does consteval guarantee about a function?

- [x] Every call is evaluated at compile time
- [ ] It runs only at run time
- [ ] It is inlined
- [ ] It cannot use loops

*Answer:* Every call is evaluated at compile time. consteval functions are immediate functions: each call must produce a compile-time constant.
