Для чего нужно ключевое слово constexpr в 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

Ответ 18+ 🔞

Ну слушай, вот есть у нас эта штука constexpr, и она, блядь, реально меняет правила игры. Представь себе: ты пишешь код, а компилятор уже на этапе компиляции всё вычисляет, как будто он заранее знает ответы на все твои вопросы. Это как списать домашку у отличника до урока — всё готово, и тебе на паре остаётся только кивать.

Короче, на что это всё похоже:

  1. Константы, которые не подведут:
    
    constexpr int SIZE = 100; // Всё, приехали. Эта сотня вшита в бинарник намертво.
    int arr[SIZE]; // И массив на 100 элементов — пожалуйста, без вопросов.

// А вот без constexpr был бы пиздец: // const int runtime_size = getSize(); // А эта функция когда выполнится? В рантайме! // 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); // Компилятор тут же, не отходя от кассы, умножает 5*4*3*2*1 = 120
    int arr[fact5]; // И спокойно создаёт массив на 120 элементов — красота!

    int x = 10; // А вот это уже переменная, её значение только в рантайме известно.
    int runtime_fact = factorial(x); // Тут уже будет обычный вызов функции, как все привыкли.
}
  1. Шаблонная магия на стероидах:
    // С C++17 появился constexpr if — это вообще песня!
    constexpr bool is_power_of_two(int n) {
    if constexpr (sizeof(int) == 4) { // Компилятор смотрит: "Ага, int у нас 4 байта"
        return n > 0 && (n & (n - 1)) == 0; // Тогда используем этот хитрый трюк с битами.
    } else {
        // А если архитектура какая-нибудь левая, то и ветка другая.
        return false;
    }
    }

А теперь главное — не путай с const, а то будет тебе хиросима!

  • const — это как обещание: "я больше не изменюсь". Но когда это обещание даётся? Может, прямо сейчас, а может, и в рантайме, когда программа уже бежит.
  • constexpr — это ультиматум компилятору: "брат, ты прямо здесь и сейчас всё посчитай и вшей в программу". Гарантия на 100%, что никакого рантайма.

Как это всё росло, как развивалось:

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

В общем, constexpr — это мощный инструмент, чтобы выжать из компилятора всё, на что он способен. Используй, и будет тебе счастье, а не просто код, который жрёт ресурсы как не в себя.