constexpr это рекомендация?
От: 00011011  
Дата: 11.04.24 07:58
Оценка:
В инете пишут что рекомендация компилятору сделать вычисление во время компиляции. Но если не получится — оставить на время выполнения.
Но зачем такое вообще нужно, если компилятор при оптимизации и так пытается вычислить что можно во время компиляции, а если не получается — генерирует код для времени выполнения?
consteval — понятно, строгое требование выполнить функцию во время компиляции и ошибка компиляции если не получается. А constexpr?
Re: constexpr это рекомендация?
От: SaZ  
Дата: 11.04.24 11:01
Оценка: +2
Здравствуйте, 00011011, Вы писали:

0>В инете пишут что рекомендация компилятору сделать вычисление во время компиляции. Но если не получится — оставить на время выполнения.

0>Но зачем такое вообще нужно, если компилятор при оптимизации и так пытается вычислить что можно во время компиляции, а если не получается — генерирует код для времени выполнения?
0>consteval — понятно, строгое требование выполнить функцию во время компиляции и ошибка компиляции если не получается. А constexpr?

А если вам надо и то и то? Там факториал какой подсчитать и во время компиляции местами, и в рантайме? Две функции писать с разными именами?
Re[2]: constexpr это рекомендация?
От: 00011011  
Дата: 11.04.24 12:52
Оценка: +1
Здравствуйте, SaZ, Вы писали:

SaZ>А если вам надо и то и то? Там факториал какой подсчитать и во время компиляции местами, и в рантайме? Две функции писать с разными именами?


Просто написать функцию факториала без каких-либо квалификаторов, в рантмайе вызывать как обычно;
а если выражение, в котором вызывается функция, требуется вычислить во время компиляции — там-то компилятор и проверит, можно ли ее вызвать при компиляции, и если нет, то выругается.

Я смотрю как сделана аналогичная фича в языке Zig, там все просто и гениально. И на фоне этого то как сделано в С++ становится совсем непонятным, почему так и чем руководствовались авторы этого constexpr?
Re: constexpr это рекомендация?
От: johny5 Новая Зеландия
Дата: 11.04.24 14:50
Оценка:
constexpr позволяет использовать функцию в контекстах где требуется только compile time константы. Раньше такое не было возможно.
Ну типа там
enum { my_val = func() };

Но сам по себе constexpr — это не оптимизация, нет смысла рекомендовать пихать его везде где можно. Как вы правильно заметили, компайлер и до этого умел оптимизировать.
Re[3]: constexpr это рекомендация?
От: Voivoid Россия  
Дата: 11.04.24 20:26
Оценка:
Здравствуйте, 00011011, Вы писали:

0>Я смотрю как сделана аналогичная фича в языке Zig, там все просто и гениально. И на фоне этого то как сделано в С++ становится совсем непонятным, почему так и чем руководствовались авторы этого constexpr?


constexpr выступает в роли контракта, который дает клиентам функции гарантии того, что функция может быть вычислена в compile time.

Допустим constexpr'а бы не было. Скажем ты используешь функцию факториала из некоторой библиотеки в compile time контексте. У функции простая реализация, поэтому все работает, все ок. Потом выходит новая версия библиотеки в которой реализация факториала изменилась ( ну не знаю, ассемблерные вставки скажем добавились ) и теперь в compile-time она вычислена быть не может. Твой код сломается при попытке перейти на новую версию. Не уверен, что ты хотел бы подобного развития событий. А вот наличие constexpr как раз исключает возможность возникновения этой ситуации.
Re: constexpr это рекомендация?
От: rg45 СССР  
Дата: 11.04.24 23:16
Оценка: +1
Здравствуйте, 00011011, Вы писали:

0>В инете пишут что рекомендация компилятору сделать вычисление во время компиляции. Но если не получится — оставить на время выполнения.

0>Но зачем такое вообще нужно, если компилятор при оптимизации и так пытается вычислить что можно во время компиляции, а если не получается — генерирует код для времени выполнения?
0>consteval — понятно, строгое требование выполнить функцию во время компиляции и ошибка компиляции если не получается. А constexpr?

constexpr позволяет использовать вызовы функций в константных выражениях:

https://timsong-cpp.github.io/cppwp/n4861/dcl.constexpr#8

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]).

--
Re: constexpr это рекомендация?
От: cppguard  
Дата: 12.04.24 01:57
Оценка: +1
Здравствуйте, 00011011, Вы писали:

0>В инете пишут что рекомендация компилятору сделать вычисление во время компиляции. Но если не получится — оставить на время выполнения.

Не очень хорошая трактовка.

constexpr это выражение, которое может быть вычисленно на этапе компиляции. То есть этим атрибутом программист сообщает компилятору, что он должен уметь вычислить выражение на этапе компиляции. Если компилятор не согласен, то он будет ругаться. А если согласен, то разрешит его использование там, где разрешены только compile-time constants. А для "ты должен вычислить это на этапе компиляции" добавили consteval.
Re[4]: constexpr это рекомендация?
От: sergii.p  
Дата: 12.04.24 08:36
Оценка:
Здравствуйте, Voivoid, Вы писали:

V>constexpr выступает в роли контракта, который дает клиентам функции гарантии того, что функция может быть вычислена в compile time.


так вот беда как раз в том, что никаких гарантий constexpr не даёт. Это только подсказка компилятору. Часто выбешивает, что надо писать тесты на то, что функция может быть вызвана в compile_time. Такие тесты простые, их можно написать по месту со static_assert, но блин, зачем писать то, что можно было бы не писать?
Re[5]: constexpr это рекомендация?
От: Voivoid Россия  
Дата: 12.04.24 10:12
Оценка:
Здравствуйте, 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];
}
Re[6]: constexpr это рекомендация?
От: sergii.p  
Дата: 12.04.24 11:08
Оценка:
Здравствуйте, 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 декларирует, но не гарантирует, что функция может быть вызвана на этапе компиляции.
Этот случай простой, его легко и глазами отследить, но бывают то вещи посложнее...
Re[7]: constexpr это рекомендация?
От: so5team https://stiffstream.com
Дата: 12.04.24 14:36
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>Он компилируется, хотя легко понять что на этапе компиляции эту функцию не вызвать. Приходится добавлять


SP>
SP>static_assert(foo() == "s");
SP>


SP>с единственной целью выяснить можно ли вызвать функцию в compile-time.


Это мне напоминает ситуацию с шаблонами:
#include <iostream>

template<typename T>
class Base {
    T _value;

public:
    Base() = default;
    ~Base() = default;
};

template<typename T>
class Derived : public Base<T> {
public:
    void f() { std::cout << "f" << std::endl; }
    void g() { std::cout << "g: " << this->_value << std::endl; }
};

int main() {
    Derived<int> d;
    d.f();
//    d.g();
}

пока не попробуешь вызвать метод g() и не узнаешь, что у тебя в коде ошибка.

Так что в этом плане ничего нового
Re: constexpr это рекомендация?
От: Pzz Россия https://github.com/alexpevzner
Дата: 12.04.24 16:27
Оценка:
Здравствуйте, 00011011, Вы писали:

0>В инете пишут что рекомендация компилятору сделать вычисление во время компиляции. Но если не получится — оставить на время выполнения.


А разве constexpr нельзя использовать там, где уместна константа? В задании размера массива, например?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.