Для чего нужно ключевое слово constexpr в C++?

«Для чего нужно ключевое слово constexpr в C++?» — вопрос из категории C++ Core, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

constexpr указывает, что значение переменной или функция могут быть вычислены на этапе компиляции, что позволяет использовать их в контекстах, требующих константных выражений.

Основные применения:

  1. Константы времени компиляции:
    
    constexpr int SIZE = 100; // Константа времени компиляции
    int arr[SIZE]; // OK - размер массива известен при компиляции

// Без constexpr было бы: // const int runtime_size = getSize(); // Вычисляется в runtime // int arr2[runtime_size]; // Ошибка: размер массива должен быть константой


2. **Функции, вычисляемые при компиляции:**
```cpp
constexpr int factorial(int n) {
    return (n <= 1) ? 1 : n * factorial(n - 1);
}

int main() {
    constexpr int fact5 = factorial(5); // Вычисляется при компиляции: 120
    int arr[fact5]; // OK - размер 120

    int x = 10;
    int runtime_fact = factorial(x); // Вычисляется в runtime, если x не constexpr
}
  1. Шаблоны и метапрограммирование:
    // С C++17 constexpr if
    constexpr bool is_power_of_two(int n) {
    if constexpr (sizeof(int) == 4) {
        return n > 0 && (n & (n - 1)) == 0;
    } else {
        // Адаптация под другие размеры int
        return false;
    }
    }

Отличие от const:

  • const - "не изменяемый после инициализации", может вычисляться в runtime
  • constexpr - гарантированно вычисляется при компиляции (если аргументы известны)

Эволюция в стандартах:

  • C++11: базовые constexpr функции
  • C++14: больше возможностей в constexpr функциях
  • C++17: constexpr if, лямбды
  • C++20: constexpr виртуальные функции, динамическое выделение памяти в constexpr