Перейти к содержанию
    

11 минут назад, RadiatoR сказал:

Почему constexpr без нее не должен работать?

Потому что constexpr это не про оптимизацию!

 

13 минут назад, RadiatoR сказал:

Подтверждаю - с O3 старый код заработал "правильно".

Скорее всего и с -О1 заработает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Constexpr это про константность результата. Он всегда один и тот же? Поменяться не может? Ни от чего не зависит? Всё! Cpnstexpr на этом заканчивается. За то как это значение получается он не отвечает. Ждём consteval.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

25 minutes ago, VladislavS said:

Потому что constexpr это не про оптимизацию!

Так я не могу понять, почему без оптимизации он вычисляется в рантайме, а не в компилтайме.

1 minute ago, VladislavS said:

Constexpr это про константность результата. Он всегда один и тот же? Поменяться не может? Ни от чего не зависит? Всё! Cpnstexpr на этом заканчивается. За то как это значение получается он не отвечает. Ждём consteval.

Аа, понял. Спасибо за разъяснение.

Тогда ждем =)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

39 минут назад, RadiatoR сказал:

Пускай сейчас она отключена и он не оптимизирует. Почему constexpr без нее не должен работать?

Думаю, дело в том, что по отношению к функциям constexpr является лишь рекомендацией. Как inline. Видимо, компилятор считает, что так отладка будет удобнее.

Кстати, есть ключ -Og, который позволяет более-менее удобно отлаживать код, при этом не отключая полностью оптимизацию.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

constexpr у функции, насколько помню, указывает, что значение функции будет константой, если все операнды функции -- константы. Например, constexpr int  max(int A, int B) -- очевидно, что если и A, и B являются константами, то максимальная из них тоже будет константой и может быть определена на этапе компиляции. Но это совершенно не требует от компилятора проводить данную оптимизацию, это лишь разрешает ему такое творить (по сути, программист с помощью constexpr обещает компилятору, что никаких побочных эффектов и неявных обращений к незнамо чему функция не выполняет). А вот использование constexpr вместо const позволяет объявить константу, под которую не выделяется память, и компилятор обязан создать константу. До появления constexpr такое только с помощью #define можно было сделать, но, понятно, это костыль. Обычный же const -- это "неизменяемая переменная", память под которую всё равно выделяется, на неё можно получить указатель и т.п., и не факт, что компилятор сможет её оптимизировать таким образом, чтобы не хранить её значение в памяти, если фактической нужды в этом нет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 minutes ago, SII said:

и компилятор обязан создать константу

Как я понял из статьи, ссылку на которую я дал выше, и это не обязательно)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, haker_fox сказал:

Как я понял из статьи, ссылку на которую я дал выше, и это не обязательно)

В случае constexrp- переменной, типа

static constexpr auto mySuperPuperConstexprVariable { 42 };

- обязательно. Если компилятор не сможет её вычислить во время компиляции, то он обязан выдать ошибку.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

18 minutes ago, AHTOXA said:

В случае constexrp- переменной, типа


static constexpr auto mySuperPuperConstexprVariable { 42 };

- обязательно. Если компилятор не сможет её вычислить во время компиляции, то он обязан выдать ошибку.

Проверил. Даже без static в случае не const вываливается с ошибкой:

volatile int ia;
constexpr int my = ia + 1;

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

Спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

49 минут назад, RadiatoR сказал:

В общем constexpr к функциям только позволяет компилятору рассчитывать в компилтайме,

Не так! Обязывает компилятор проконтролировать константность возвращаемого результата. Если значение  функции будет вычисляться из чего-то неконстантного, то получишь ошибку. Вычислять в компайлтайме компилятор может и без всяких conxtexpr,  достаточно включить оптимизацию. Убери из примера в первом сообщении все constexpr и ничего вообще не изменится. Constexpr для функции это средство контроля.

 

Static это вообще из другой оперы, с const и constexpr вообще никак не связано.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

41 минуту назад, VladislavS сказал:

Не так! Обязывает компилятор проконтролировать константность возвращаемого результата. Если значение  функции будет вычисляться из чего-то неконстантного, то получишь ошибку.

Ну здрасьте. Только вроде бы всё выяснили, и всё снова :-)

Вот пример (можно потыкать онлайн):

constexpr unsigned square(unsigned i)
{
    return i * i;
}

constexpr auto ci { 0u };

int main()
{
    unsigned t = std::time(0);
    
    std::cout << "Вызов с константой: " << square(2) << std::endl;
    std::cout << "Вызов с переменной: " << square(t) << std::endl;
}

Значение функции вычисляется из неконстантного аргумента. И никакой ошибки.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 минуты назад, AHTOXA сказал:

Значение функции вычисляется из неконстантного аргумента. И никакой ошибки.

Опередили меня. Слишком долго с телефона набирал :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 minutes ago, AHTOXA said:

Значение функции вычисляется из неконстантного аргумента. И никакой ошибки.

Получается, при включенной оптимизации, constexpr для функций вообще ничего не значит...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не совсем так. Результат вызова constexpr-функции можно присваивать constexpr-переменной. А результат вызова не-constexpr-функции - нельзя:

int f1(int i) { return i * i; }

constexpr int f2(int i) { return i * i; }

int main()
{
    constexpr auto i1 = f1(2);  // ошибка!
    constexpr auto i2 = f2(2);  // порядок.
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 минуту назад, AHTOXA сказал:

Результат вызова constexpr-функции можно присваивать constexpr-переменной.

Вот в этом случае будет 100% гарантия того, что все вычислилось во время компиляции, если не будет ошибок от компилятора. Не придется открывать листинг :)

В общем случае я бы не стал смешивать constexpr и оптимизацию. Оптимизация будет зависеть от конкретного компилятора, поэтому нельзя, глядя на код, предугадать, что будет вычисляться во время компиляции, если не указать constexpr. В случае из цитаты @AHTOXA такой неоднозначности нет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Действительно.

#include <iostream>
#include <cstdlib>

constexpr int f2(int i) { return i * i; }

int main()
{
    volatile int x;
    constexpr auto i2 = f2(x);  // ошибка.
}

Проверил этот код. Тоже вываливается с ошибкой. В итоге выходит, что constexpr к функции ничего не "должна". А к переменной предъявляет однозначный расчет в компилтайме и присвоение через constexpr функцию, либо напрямую константой.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...