Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
constexpr char* s = "str";
constexpr char* q = s + 10; // не скомпилируется
constexpr-функции. В случае деления на ноль, компилятор выдаст ошибку, показывая при этом стек вызовов.constexpr-функциях все переменные должны быть инициализированы, из-за чего не получится использовать неинициализированную переменную.constexpr затрудительно. Но это можно сделать, запустив функцию в runtime (например, передав в качестве параметра не constexpr-переменную).error: constexpr variable cannot have non-literal type 'const std::regex' (aka 'const basic_regex<char>')
constexpr std::regex pattern("(0-9)");constexpr regex. Вообще после С++14 из-за того, что уберут много ограничений на constexpr-функции и классы, можно будет почти всю стандартную библиотеку переписать, используя constexpr.constexpr как раз это и позволяет сделать (в C++11 не очень удачно). Но преимущество constexpr-функций в том, что в случае невозможности вызова функции на этапе компиляции, она запуститься в runtime, из-за чего не надо будет делать два экземпляра каждой функции.constexpr-переменной.constexpr int n = get_n(); // теперь в случае невозможности использовать constexpr-функцию будет выведена ошибка
#include <iostream>
struct foo {
int bar;
foo(int bar) : bar(bar) {}
const int &getBar() {
return bar;
}
};
int main () {
foo f(5);
int bar = f.getBar();
bar = 10;
std::cout << f.bar << " " << bar << std::endl; // 5 10
}
добро пожаловать под кат!
constexpr int b = inc (a); // ошибка: преобразование int -> constexpr int
int в constexpr int, а в том, что a не является constexpr выражением, а такого типа, как constexpr int вообще не существует, так как constexpr не является частью типа, поэтому никаких попыток преобразования не делается.То есть не получится создать исключительно constexpr-функцию, которая может работать только на этапе компиляции.
constexpr int inc (int a)
{
return a + 1;
}
Также constexpr-функции могут работать с объектами, это будет рассмотрено позже.
constexpr int b = inc (a); // ошибка: преобразование int -> constexpr int
Это неверно. Ошибка в данном случае заключается не в том, что происходит попытка преобразования int в constexpr int, а в том, что a не является constexpr выражением, а такого типа, как constexpr int вообще не существует, так как constexpr не является частью типа, поэтому никаких попыток преобразования не делается.
То есть не получится создать исключительно constexpr-функцию, которая может работать только на этапе компиляции.
Вот это тоже непонятно.
Также constexpr-функции могут работать с объектами, это будет рассмотрено позже.
Непонятная фраза. Могут работать с объектами? А обычные не могут?
Любую constexpr-функцию можно запустить в runtime, для этого достаточно передать аргумент, который нельзя посчитать на этапе компиляции.
Параметры функций не могут быть constexpr. То есть не получится создать исключительно constexpr-функцию, которая может работать только на этапе компиляции.
constexpr int foo(int i); // Здесь foo() может быть вычислена и в рантайме и в
const int j = foo(2); // компайлтайме, несмотря, что её аргументом является constexpr
constexpr int foo(int i); // А здесь foo() обязаны быть вызвана в
constexpr int j = foo(2); // компайлтайме
constexpr int foo(int i); // Здесь foo() может быть вычислена и в рантайме и в
const int j = foo(2); // компайлтайме, несмотря, что её аргументом является constexpr
constexpr int foo(int i); // А здесь foo() обязаны быть вызвана в
constexpr int j = foo(2); // компайлтайме
constexpr-переменной, так как функция обязана вызвана в compile-time, если ее параметры можно посчитать на этапе компиляции.y не будет равняться нулю, то кусок кода после '?' будет проигнорирован. Но чтобы вопросов не было, можно это переписать таким образом:return (y == 0)? (throw std::logic_error («x can't be zero»), 0): (y / x);
Когда пишешь какую-то constexpr-функцию, которую потом будут часто использовать, хорошо бы возвращать читабельную ошибку. Тут можно ошибочно предположить, что static_assert как раз для этого подходит. Но static_assert использовать не получится, так как параметры функций не могут быть constexpr, из-за чего значения параметров не гарантированно будут известны на этапе компиляции.
Начиная с C++14 constexpr может работать и в не константном режиме.Начиная с C++11.
Но обратно не работает, такой дизайн.Такая ошибка в дизайне. Очень большая, серьёзная и неприятная.
Программист ведь имеет право не обозначать функцию constexpr, например в тех случаях когда он явно знает, что она не является чистой.Однако он обязан это сделать в тех случаях, когда он хочет, чтобы её можно было использовать в
constexpr-выражениях. Однако зачастую — не может. Ибо в разных версиях C++ требования к constexpr-функциям разные и вы не можете пометить функцию как constexpr и сказав в документации «на старых C++ комиляторах эту функцию нельзя использовать в constexpr-выражениях». Вам приходится либо писать «для использования этой библиотеки вам потребуется C++17 компилятор», либо обмазывать всё ваше творение кучей #ifdefов.constexpr-выражениях!constexpr-выражениях!constexpr int badfunc(bool to_be) {
if (to_be or not to_be) {
printf("Yeah, we are here!\n");
}
return 0;
}И как вы собрались применять её?constexpr спецификатор в применении к функции — это 100% ошибка дизайна. Очень глупая. Хотя во времена C++11 она казалась разумной — но дальнейшее развитие языка показало, что это ни разу не так.
Спецификатор constexpr в C++11 и в C++14