constexpr -> константа времени компляции, constant expression
constexpr > const
constant expressions - особый вид выражений, которые можно подставлять в шаблонные параметры и использовать для инициализации constexpr переменных
для переменных constexpr => const
constexpr переменная (С++11): заставляет компилятор гарантировать, что значение этой переменной известно на момент компиляции (иначе CE). константа, гарантированно известная на момент компиляции
constant expression - выражение времени компиляции
if constexpr (C++17) говорит компилятору, что нужно выкинуть этот if из кода, если условие в ифе ложное (условие должно быть проверяемо в compile time, а также энивей будет синтаксически распаршено)
до С++17 без if constexpr надо было делать несколько перегрузок функций, в которых доп. аргумент - причина выбора той или иной перегрузки
constinit переменная (C++20): может применятся только к переменным, имеющим static или thread-local storage duration. гарантирует, что переменная будет инициализирована constant expression на этапе компиляции. нужно для того, чтоб статические переменные не инициализировались динамически, что может вызвать конфликты, если другим единицам трансляции нужна эта переменная, тк порядок динамической инициализации между единицами трансляции не определён
не является const, но можно навесить
constexpr функции - вызов этой функции мы хотим считать constant expression (то, что может быть вычислено на этапе компиляции), никак не связано с const
любую функцию, которую мы хотим вызвать в compile-time должна быть constexpr
не обязательно вычисляется в compile-time, не обязывает вызывать только от constant expressions. означает лишь, что мы можем использовать вызов этой функции там, где ожидается constexpr
любые built-in операторы над примитивными типами - constexpr
в constexpr функции могут быть declarations и control statements с C++14
до C++14 можно было только return expression
вещи, которые требуют constexpr от аргумента:
- шаблонные аргументы
static_assert- инициализация constexpr переменной
static constпеременные
constexpr функции могут вычисляться как в compile-time, так и в runtime
в constexpr функциях можно заставить компилятор в compile-time создать массив на стеке , делать указатели и арифметику над ними, разыменовывать
если разыменовать невалидный указатель в constexpr это будет ошибка компиляции
переполнение инта в compile time это CE
то есть UB в compile-time превращается в CE
то есть в constexpr c++ безопасный язык (без UB*), но работает медленнее
* UB x++ + ++x все равно в compile time не задетектится (не могут добавить в компиляторы, чтоб это детектилось)
throw в constexpr функциях писать можно, при условии, что до него не дойдёт исполнение
если оно попытается выкинуть, то будет CE non-constant condition in constexpr
можно так специально сделать для throw-idiom
ловить исключения в compile time нельзя
вызов нетривиального конструктора или деструктора, который не помечен constexpr - требует вызова не-constexpr функции на стеке
перегружать по constexpr нельзя, тк constexpr не часть сигнатуры
объект можно сделать параметром шаблона, если у него constexpr конструктор
если у объекта constexpr конструктор, то он литерал
virtual функции могут быть constexpr
не constexpr функция может заоверрайдить constexpr, но компиляция упадёт при попадании в эту функцию
constexpr virtual функции могут вычислиться в compile-time, то есть все vtable создадутся и будет работать.
(C++20) dynamic_cast можно делать в compile-time. если сделать неправильный dynamic_cast, то выкинется вместо std::bad_cast - CE
(C++17) можно создавать constexpr лямбды
лямбды по умолчанию считаются constant expression
(C++20) можно делать new в compile time
утечка памяти в compile time - CE
вылетит ошибка “is not constant expression because allocated storage has not been deallocated”
также double free, delete не по тому поинтеру, delete вместо delete[] вместо UB становится CE
если будет запрошено слишком много памяти, то он упадёт как при слишком глубокой шаблонной рекурсии - будет слишком много запрошено памяти для компиляции
все конструкторы и методы std::string и std::vector начиная с C++20
constexpr для функций влечёт inline
constexpr для переменных влечёт const
consteval (C++20)
если constexpr функции такие, которые могут быть вызваны в compile time, но их можно вызывать и в runtime, то consteval гарантирует, что вызов будет происходить только в compile time. запрещает вызов в runtime применимо только к функциям
с C++20 есть функция std::is_constant_evaluated() проверяет находимся ли мы в constexpr контексте или нет
с C++23 можно писать if consteval - true если в compile time, иначе else не нужно писать consteval или is_constant_evaluated под if constexpr, потому что там оно всегда true