TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.35K subscribers
Post #779 4.65K
constexpr функции сквозь года
#новичкам

constexpr бывают не только переменные, но и функции. Такие функции могут быть выполнены, как в compile-time, так и в runtime, в зависимости от контекста вызова:
- Если значения параметров возможно посчитать на этапе компиляции, то возвращаемое значение также должно посчитаться на этапе компиляции.
- Если значение хотя бы одного параметра будет неизвестно на этапе компиляции, то функция будет запущена в runtime.
- Если вы попытаетесь присвоить возвращаемое значение функции с runtime аргументом constexpr переменной, то получите ошибку компиляции.

constexpr int square(int x) {
return x * x;
}

int main() {
constexpr int val = square(5); // compile-time calculations
static_assert(val == 25, "Must be 25"); // compile-time check
int arg = rand() % 25;
int res = square(arg); // runtime calculations
assert(res == arg*arg); // runtime check
constexpr int fail = square(arg); // compile error here!
}


Пройдемся по стандартам языка и посмотрим, как в них изменялись constexpr функции.

В С++11 можно было использовать только однострочные constexpr функции с сильными ограничениями.


constexpr int factorial(int n) {
// ternary operator is allowed, so recursion
return (n <= 1) ? 1 : n * factorial(n - 1);
}


В С++14 уже можно писать многострочные функции, использовать в них локальные переменные и базовые конструкции языка, кроме try-catch(там динамические аллокации, с которыми трудно в compile-time), goto(открестились и правильно сделали) и еще пары менее значимых моментов:

constexpr int factorial(int n) {
int result = 1;
for (int i = 2; i <= n; ++i) {
result *= i;
}
return result;
}

static_assert(factorial(5) == 120, "Must be 120");


C++17 - constexpr лямбды. За это отдельный лайк 17-му стандарту, но помимо этого ничего существенного не привнеслось:

constexpr auto factorial = [](int n) {
int result = 1;
for (int i = 2; i <= n; ++i) {
result *= i;
}
return result;
};

static_assert(factorial(5) == 120, "Must be 120");


C++20 и выше - constexpr почти везде. Уже есть и виртуальные constexpr функции, и исключения можно в compile-time отлавливать, и большинство простых контейнеров могут быть созданы и препарированы в compile-time, и все больше алгоритмов и стандартных функции получают пометки constexpr.

constexpr std::string create_greeting() {
std::string s = "Hello, ";
s += "C++20!";
return s;
}

static_assert(create_greeting() == "Hello, C++20!");


constexpr функции помогают иметь единый интерфейс для runtime и compile-time вычислений. Поэтому использование таких функций может приводить к неожиданному переносу некоторых вычислений в compile-time.

В сферах, где важны ультра-мега-милипизерные задержки очень важно как можно больше действий перевести в compile-time + сильно разгрузить "разогрев" программы , чтобы оставить время выполнения только для самых важных вещей(лутание бабок).

Free up time for important things. Stay cool.

#cpp11 #cpp14 #cpp17 #cpp20
  • 🔥 31
  • 👍 12
  • ❤ 6
  • 👎 2
More from @grokaemcpp
  1. Oct 12, 2026​​WAT #новичкам Как вы думаете, результат выражения: bool math = -1 < 1U; будет правдой ил…
  2. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  3. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  4. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  5. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
  6. Sep 28, 2026​​Stacktrace #опытным Одна из проблема исключений - непонятно, откуда оно прилетело. Ну да…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →