В инете пишут что рекомендация компилятору сделать вычисление во время компиляции. Но если не получится — оставить на время выполнения.
Но зачем такое вообще нужно, если компилятор при оптимизации и так пытается вычислить что можно во время компиляции, а если не получается — генерирует код для времени выполнения?
consteval — понятно, строгое требование выполнить функцию во время компиляции и ошибка компиляции если не получается. А constexpr?
Здравствуйте, 00011011, Вы писали:
0>В инете пишут что рекомендация компилятору сделать вычисление во время компиляции. Но если не получится — оставить на время выполнения. 0>Но зачем такое вообще нужно, если компилятор при оптимизации и так пытается вычислить что можно во время компиляции, а если не получается — генерирует код для времени выполнения? 0>consteval — понятно, строгое требование выполнить функцию во время компиляции и ошибка компиляции если не получается. А constexpr?
А если вам надо и то и то? Там факториал какой подсчитать и во время компиляции местами, и в рантайме? Две функции писать с разными именами?
Здравствуйте, SaZ, Вы писали:
SaZ>А если вам надо и то и то? Там факториал какой подсчитать и во время компиляции местами, и в рантайме? Две функции писать с разными именами?
Просто написать функцию факториала без каких-либо квалификаторов, в рантмайе вызывать как обычно;
а если выражение, в котором вызывается функция, требуется вычислить во время компиляции — там-то компилятор и проверит, можно ли ее вызвать при компиляции, и если нет, то выругается.
Я смотрю как сделана аналогичная фича в языке Zig, там все просто и гениально. И на фоне этого то как сделано в С++ становится совсем непонятным, почему так и чем руководствовались авторы этого constexpr?
constexpr позволяет использовать функцию в контекстах где требуется только compile time константы. Раньше такое не было возможно.
Ну типа там
enum { my_val = func() };
Но сам по себе constexpr — это не оптимизация, нет смысла рекомендовать пихать его везде где можно. Как вы правильно заметили, компайлер и до этого умел оптимизировать.
Здравствуйте, 00011011, Вы писали:
0>Я смотрю как сделана аналогичная фича в языке Zig, там все просто и гениально. И на фоне этого то как сделано в С++ становится совсем непонятным, почему так и чем руководствовались авторы этого constexpr?
constexpr выступает в роли контракта, который дает клиентам функции гарантии того, что функция может быть вычислена в compile time.
Допустим constexpr'а бы не было. Скажем ты используешь функцию факториала из некоторой библиотеки в compile time контексте. У функции простая реализация, поэтому все работает, все ок. Потом выходит новая версия библиотеки в которой реализация факториала изменилась ( ну не знаю, ассемблерные вставки скажем добавились ) и теперь в compile-time она вычислена быть не может. Твой код сломается при попытке перейти на новую версию. Не уверен, что ты хотел бы подобного развития событий. А вот наличие constexpr как раз исключает возможность возникновения этой ситуации.
Здравствуйте, 00011011, Вы писали:
0>В инете пишут что рекомендация компилятору сделать вычисление во время компиляции. Но если не получится — оставить на время выполнения. 0>Но зачем такое вообще нужно, если компилятор при оптимизации и так пытается вычислить что можно во время компиляции, а если не получается — генерирует код для времени выполнения? 0>consteval — понятно, строгое требование выполнить функцию во время компиляции и ошибка компиляции если не получается. А constexpr?
constexpr позволяет использовать вызовы функций в константных выражениях:
An invocation of a constexpr function in a given context produces the same result as an invocation of an equivalent non-constexpr function in the same context in all respects except that
— an invocation of a constexpr function can appear in a constant expression ([expr.const]) and
— copy elision is not performed in a constant expression ([class.copy.elision]).
Здравствуйте, 00011011, Вы писали:
0>В инете пишут что рекомендация компилятору сделать вычисление во время компиляции. Но если не получится — оставить на время выполнения.
Не очень хорошая трактовка.
constexpr это выражение, которое может быть вычисленно на этапе компиляции. То есть этим атрибутом программист сообщает компилятору, что он должен уметь вычислить выражение на этапе компиляции. Если компилятор не согласен, то он будет ругаться. А если согласен, то разрешит его использование там, где разрешены только compile-time constants. А для "ты должен вычислить это на этапе компиляции" добавили consteval.
Здравствуйте, Voivoid, Вы писали:
V>constexpr выступает в роли контракта, который дает клиентам функции гарантии того, что функция может быть вычислена в compile time.
так вот беда как раз в том, что никаких гарантий constexpr не даёт. Это только подсказка компилятору. Часто выбешивает, что надо писать тесты на то, что функция может быть вызвана в compile_time. Такие тесты простые, их можно написать по месту со static_assert, но блин, зачем писать то, что можно было бы не писать?
Здравствуйте, sergii.p, Вы писали:
SP>так вот беда как раз в том, что никаких гарантий constexpr не даёт. Это только подсказка компилятору. Часто выбешивает, что надо писать тесты на то, что функция может быть вызвана в compile_time.
Не совсем понятно о чем именно речь. А можно пример кода?
А вообще:
constexpr size_t fac(size_t n) // спецификатор constexpr гарантирует, что функция вычислится в compile-time ЕСЛИ её вызывают в compile-time контексте
{
if (n == 0) return 1;
return n * fac(n - 1);
}
int main() {
auto r1 = fac(5); // здесь никаких гарантий compile-time выполнения нет. Оптимизатор возможно заоптимизирует, а возможно и нет.
constexpr auto r2 = fac(5); // здесь гарантируется, что переменная r2 будет вычислена на этапе компиляцииint arr1[fac(5)]; // размеры массивов будут вычислены на этапе компиляцииint arr2[r2];
}
Здравствуйте, Voivoid, Вы писали:
V>Не совсем понятно о чем именно речь. А можно пример кода?
такой код рассмотрим:
constexpr std::string_view foo() {
auto p = new char[10];
p[0] = 's';
p[1] = 0;
return p;
}
Он компилируется, хотя легко понять что на этапе компиляции эту функцию не вызвать. Приходится добавлять
static_assert(foo() == "s");
с единственной целью выяснить можно ли вызвать функцию в compile-time. Хотя я уже добавил constexpr и хотел бы чтобы компилятор сам всё проверил и выдал ошибку. То есть добавление constexpr декларирует, но не гарантирует, что функция может быть вызвана на этапе компиляции.
Этот случай простой, его легко и глазами отследить, но бывают то вещи посложнее...
Здравствуйте, 00011011, Вы писали:
0>В инете пишут что рекомендация компилятору сделать вычисление во время компиляции. Но если не получится — оставить на время выполнения.
А разве constexpr нельзя использовать там, где уместна константа? В задании размера массива, например?