Многие операции с volatile устарели в c++20 (см. https://en.cppreference.com/w/cpp/language/cv)
Итак.... когда я использовал очень популярную библиотеку glm (https://github.com/g-truc/glm) в своем проекте, я получил предупреждения об этом коде (файл type_half.inl)
GLM_FUNC_QUALIFIER float overflow()
{
volatile float f = 1e10;
for(int i = 0; i < 10; ++i)
f *= f; // this will overflow before the for loop terminates
return f;
}
Этот код используется для принудительного переполнения с плавающей запятой, и, очевидно, volatile здесь используется для отключения оптимизации вокруг f. В противном случае компилятор может просто выкинуть этот цикл за ненадобностью.
Как этот код можно исправить для современных стандартов С++, таких как С++ 20 и выше?
вы можете заменить использование volatile с помощью std:atomic
Отключение предупреждений - очень плохая практика!! Это абсолютно не вариант. @ПолСандерс
std:atomic - тяжеловес для этого, так как вдобавок нет необходимости в потокобезопасности или барьерах
Проверьте это и выбросьте volatile, никогда не было безопасно использовать его для отключения оптимизации. stackoverflow.com/questions/40122141/… Также вас может заинтересовать реализация DoNotOptimize google/benchmark: github.com/google/benchmark/blob/main/include/benchmark/…
Отключение предупреждений - очень плохая практика!! Это абсолютно не вариант. Вы бы сделали это только для тех файлов, которые в этом нуждаются... Смотрите также: stackoverflow.com/questions/3378560/…
@fsmoke: Есть ли какая-то причина, по которой функция просто не возвращает numeric_limits<float>::infinity(), поскольку именно это происходит, когда вы переполняете число с плавающей запятой IEEE-754?
@EricPostpischil, предупреждение: составное присваивание с «изменчивым» левым операндом устарело [-Wvolatile]
@NicolBolas, похоже, возвращаемое значение этой функции всегда отбрасывается - эта функция используется только для переполнения с плавающей запятой (т.е. генерирует исключение FPU, если такая опция включена)
Отключение предупреждений - очень плохая практика" Работа с абсолютами - плохая практика. Да, я бы не стал отключать его глобально, но отключать его для определенного файла или строк можно.





Очевидное решение — удалить *=: f = f * f;. Код не требует особого поведения вне *=; он просто хочет, чтобы компилятор не оптимизировал операции умножения. В той мере, в какой volatile заставляет компилятор делать это, он будет работать так же хорошо с f = f * f;.
ДА это работает!! предупреждения теперь подавлены! спасибо
@fsmoke: вы должны отправить это в репозиторий GLM Github в качестве запроса на выпуск / вытягивание.
да думаю завтра(сейчас вечер - я уже устал) создам новый pull-request в glm repo
хахаха - я только что клонировал основную ветку glm - и там это предупреждение уже исправлено - как вы предлагаете f = f * f :)))) - так что... все уже сделано, без нас
"Очевидное решение" Можете ли вы объяснить очевидную часть? У меня может быть неправильная ментальная модель относительно разницы двух выражений (нет для тривиальных типов, таких как float)
@MatG: я не понимаю. Вы, кажется, понимаете, что в этом случае нет никакой разницы между двумя выражениями, за исключением того факта, что одно является законным, а другое - допустимым, но устаревшим. Так что ... используйте легальный. Это очевидная часть. Весь смысл осуждения *= и ему подобных volatile состоит в том, чтобы дать понять, что вы знаете, что это не одна атомарная операция. f = f * f; проясняет это так, как f *= f; нет.
@MatG, разница между операциями такова: f*=f эта операция над lvalue - устарела, но f=f*f прямое назначение - разрешено новым стандартом. Внимательнее перечитайте cppreference в моем стартовом посте.
Отключить предупреждение? (Компилятор должен сказать вам, какой флаг использовать в командной строке)