Комментарии 41
35 лет активно пишу на Си, вот ни разу не нарывался на ошибку, связанную с тем, что в условии вместо сравнения случайно оказывалось присваивание.
На многие другие популярные ошибки нарывался, а вот на эту - вообще никогда. Наверное, это очень индивидуально.
И очень уж чудно это выглядит, if (2 == x) .... Может не стоит давать такие советы, как универсальные?
P.S. Современные компиляторы выдают предупреждение, если случайно перепутать присваивание со сравнением. Идея включать предупреждения по максимуму и не игнорировать их - хорошая, годная.
включать предупреждения по максимуму
...или просто использовать статический анализатор

Предупреждения компилятора - это маленький статический анализатор, который всегда с собой.
Он, может, и не такой дотошный, как внешние анализаторы (хотя компиляторы постепенно умнеют в этом плане). Но он не требует отдельного инструмента, не требует подстройки под затеи вашей сборочной системы. Достаточно лишь разрешить компилятору это делать, и он сделает, заодно с компиляцией.
заодно с компиляцией
Я писал код в таком режиме несколько лет, без всяких intellisense и статических анализаторов - просто в vim без плагинов: пишешь несколько сотен строк, потом (зачастую) читаешь портянку, которую выдаёт компилятор, потом исправляешь; и так в цикле, пока не будет ошибок и предупреждений; а ведь потом ещё отлаживать. Опыт не самый лучший, открыл для себя vscode, стало проще (да, жрущий электрон с плагинами на джаваскрипте) - всё в реальном времени: пишешь, сразу же исправляешь косяки свои; и тут же в git выделяешь нужные изменения, коммитишь и т.д.
Я повесил в vim-е вызов команды make на hotkey, и после каждых нескольких строк его нажимаю.
И да, я до сих пор пишу в vim.
Нахожу чертовски неудобными системы сборки, которые не позволяют сказать make локально, прямо в рабочей директории.
после каждых нескольких строк его нажимаю
Почти как привычка сохранять файл у некоторых)
Про системы сборки: для C и C++ стараюсь использовать CMake, где возможно (если проект сам в себе; если либы поддерживают или легко адаптируются под CMake), который уже генерирует Makefile или Ninja, где как лучше, а также compile_commands.json для clangd. С ним удобнее поддерживать зависимости в порядке и в целом проще иерархию проекта строить.
Сейчас активно пробую Rust, там вообще уже всё предусмотрено - и пакетный менеджер, и система сборки, и статический анализатор, и даже тестирование; пока моё мнение складывается не в пользу C/С++ (по большей части).
Почти как привычка сохранять файл у некоторых)
А оно заодно и файл сохраняет
Про системы сборки: для C и C++ стараюсь использовать CMake
Если честно, я ненавижу cmake
Сейчас активно пробую Rust, там вообще уже всё предусмотрено
Мой второй язык - Go. Насколько я понимаю, там со сборкой, как в Rust. И очень подозреваю, что в Rust оно из Go и попало...
В моем vim-е настроен автокомплит и такие ошибки подсвечиваются сразу, без явного вызова компиляции.
Ну в первую очередь речь идёт о языках-наследниках C, где имеется динамическая типизация. В C# и Java - применяемость ограничена.
В PHP или в JS вы не получите ничего по ошибкам. Кроме как непонятно что делающего кода. Особенно это плохо когда условие редко исполняемое.
В чистом Си, насколько помню (очень давно на нём писал) у вас в ряде компилятором действительно вылезет ошибка - самостоятельный typecast не случится, и булево значение в условии не появится.
Ну, JS хоть и создан по принципу, "любая последовательность символов является синтаксически корректной программой", но присвоить значение переменной константе и он вроде не даст...
А ещё в JS всё-таки в большей степени принято строгое сравнение ===, которое ещё сложнее случайно перепутать с присваиванием) и в целом проблема в контексте JS может быть актуальна только для тех, кто IDE использует видимо как блокнот(когда реально всё выглядит как одна большая строка), и про тайпскрипт слышать не хочет. Кажется, автор очень сильно застрял в прошлом
Откройте для себя статические анализаторы. Они предупредят о возможной ошибке присваивания в условии.
Например,
#include <stdio.h>
int main() {
int t = 0;
if (t = 1) {
printf("T is 1\n");
} else {
printf("T is not 1\n");
}
}
И вот что говорит про этот код PVS-Studio:
<source>:5:1: warning: V547 Expression 't = 1' is always true.
<source>:5:1: warning: V559 Suspicious assignment inside the conditional expression of 'if' statement: t = 1.
А Йода-стиль подходит только для сравнения с константами. Если у вас с обоих сторон переменные, то никакой ошибки при компиляции вы не получите.
Безусловно при двух переменных - нам это не поможет. А может быть ещё больше запутает.
Но в случаях с: конкретным значением, результатом другой функции, константой - оно сработает..
Сработает. Но статический анализ сработает лучше. А заодно и покажет другие потенциальные ошибки.
Пардонь-те, но в списке хабов указан C++, поэтому:
Одна из проблем инверсии в том, что результат (a == b) может быть не равен результату (b == a). В C++, особенно когда типы разные - легко. Поэтому начиная читать статью предполагал описание таких случаев и как от них уберечься, то есть меньше стрелять в ногу.
Но здесь рассуждения про йода-стиль. Ок, стиль работает в своей области. Но соглашусь в другими комментирующими: предупреждения компилятора творят чудеса - используйте их. А со статическим анализатором и предупреждениями компилятора можно добиться большего, чем просто с предупреждениями компилятора.
Что касается упоминаний констант и результатов функции, то тут лучше быть поаккуратнее. Приведённый ниже код использует присваивание в константу и результат функции, он компилируется (но компилятор может насыпать предупреждений) и работает:
#include <iostream>
class A {
public:
A(int) {}
const A& operator=(int) const { return *this; }
operator bool() const { return true; }
};
int g_value = 0;
int& funcB() {
return g_value;
}
int main()
{
const A const1 = 5;
int v1 = 10;
if (const1 = v1) {
std::cout << "success" << std::endl;
}
if (funcB() = v1) {
std::cout << "success" << std::endl;
}
return 0;
}
Кстати, в случае с функцией уже могут быть проблемы в порядке вычислений. Сравниваемая переменная может менять значение при вычислении функции и варианты a == f() и f() == a могут давать разный результат.
маленький код под С/С++ стат анализ ок, чуть больше я даже не понимаю контекста, я сколько не пробовал, эта шарманка начинает использовать проц(по моей оценке это спам нагрузкой цпу при вводе текста при анализе) на моей тачке, ради того чтобы проверить код, когда в Расте+(неупомянутый редактор текста) со статой и компиляцией всё ожидаемо(в этой связке нету спама - Раст+неупомянутый редактор текста) и очевидно (плата по озу очевидна, но редактор и Раст работают ожидаемо, в то время когда и вижуал студия, и вскод, и кути(даже иногда) грешат спамом нагрузки цпу при вводе текста)
это в копилку визуал студии и С языков, разбираться с этим даже нету желания(всмысле что нагружает и поэтому отталкивает)
в С++ до сих пор непонятно с модулями еще тоже, после раста отталкивает
мой итог по моим наблюдениям: у раста анализ лучше и неупомянутого редактора нету спама нагрузкой цпу при большом проекте - это услада для меня, возращаюсь в С++ иногда - тесты делаю, всё неизменно, и после раста с модулями, да пускай неполноценная тема с модулями но удобно, С++ какой-то громоздкий уже кажется, а после попыток компиляций G3D, я вообще понял, что стандарты и любые новшества меняют экосистемы настолько - очень сильно кароче
попробуйте собрать на генте G3D вы возможно пересмотрите что-то в софтовом подходе и создании чего-либо
нужна ожидаемость, предсказуемость, понятная многопоточка, детерминизм для слоя программирования, и никаких icompile, каких-то флагов, которые не существуют, или ситуации как с питоном 2, только представьте сегодня мы кодим пользуемся всякими сборщиками, через время, экосистема изменится, никто даже разбираться не будет почему не собирается
сегодня компайлер строгий через 20 лет станет снова добрый, тоже самое может ждать раст, но посмотрим, но кароче при всех прочих, что я видел, у С/С++ больше этой боли
Теперь не понятно стало. То-ли человек не умеет мысли формулировать, то-ли и в комменты с llm пришли... :(
ну при вводе текста статический анализатор ест цпу в визуал студио(и вскод такой же) например и даже в кути, по мере роста кодовой базы, пропорционально от количества кода, когда на расте и неупомянутом редакторе нету спама по цпу в момент анализа при вводе текста
тоесть инструменты С/С++ работают неожидаемо, недетерминированно(а значит и многопоточка не интуитивная например - это же всё взаимосвязано получается), при вводе текста при анализе ведь получается если прагматически честно смотреть на это
как бы это не звучало странно загружаем анриал енджин и пишем код(визуал студио/вскод/кути любой на выбор), будет там рекомпил на фоне, конечно, ведь так происходит проверка, почему так я даже знать не хочу
простите задам вам вопрос, при вводе текста в момент анализа должен быть спам по цпу? или вы считаете я галюцинирую?
тоесть мы вернёмся к вопросу доступности модулей, хорошо если они из коробки в инструменте, а так придётся компилировать интструмент - компилятор наверно, и еще вникать как завести модуль, когда в расте это делается проще
тоесть затраченный труд на использование высокой логики, борьба с инструментами как со стенами, когда можно просто писать код и компилировать как в расте
Вопрос: что будет делать автор, если надо сравнить две переменных? В какой последовательности он будет их писать?
А по факту, решений этой проблемы немного:
запретить выражение присваивания внутри условия: в императивных языках позволять присваивать в условии бессмысленно - ничего кроме усложнения чтения это не дает. Вместо линейного чтения человек вынужден прыгать в середину выражения, и раскручивать понимание "вширь". Ради чего такие упражнения?;
или обязать дополнять выражение присваивания внутри условия каким-то ключевым словом, которое говорит: я понимаю что я делаю;
или убрать из языка синтаксис присваивания, близко похожий на проверку условия;
Щас сюда набегут адепты сишо-плюсов, и будут кричать что тот кто ошибается в таких простых вещах, не имеет права быть программистом :).
При двух переменных - вы лишь имеете право выбора, в какую из ног в случае чего будете стрелять :)
Запрет присваивания (упомянул в статье) есть в Go и Python. Но не везде.
Убрать синтаксис присваивания - невозможно по сути. У нас такое огромное наследие Си, что...
Ну а вы бы сами тогда как бы обозначили бинарный оператор присваивания?
Щас сюда набегут адепты сишо-плюсов, и будут кричать что
Вероятно я сейчас за эти слова отхвачу по полной. Но... ничего страшного - пусть прибегают. Нужно же людям как-то развлекаться? :)
Сейчас придут адепты старой школы, и скажут, что это - самый канонический способ написания копирования строк, завещанный нам отцами нашими Керниганом и Ричи:
while (*d ++ = *s ++)
;
А потом нехороший человек затирает нулевой символ у s.
while (*d ++ = *s ++);
Как меня раздражают вот эти вот потуги писать код в виде ребусов, причем намеренно вводя пользователя в заблуждение. То есть, как бы говоря: не расслабляйся, давай-ка в очередной раз проверим твою внимательность и память, заодно потестируем твое умение справляться с когнитивными нагрузками! Ведь ты же этим должен заниматься когда программируешь на сишечке, других забот у тебя нет.
Зачем объединять лексемы не в той последовательности, в которой они будут выполняться? Зачем прилеплять звездочку indirection к имени, а инкремент - писать отдельно? Потому что синтаксис позволяет? А почему бы не показать приоритет операций, чтобы не лезть в документацию? Ну напишите вы:
while( *(d++) = *(s++) );
и все сразу становится на свои места. Но нет, мы будем извращаться.
В боевом коде я вот так вот напишу:
while (*s != '\0') {
*d = *s;
s ++;
d ++;
}
Потому что я зануда хочу избежать по возможности недопонимания среди возможных читателей
в VisualStudio в редакторе сразу выдаст предупреждение о недостижимости кода . смысл костылей ?
Хорошо. А будете делать, если вдруг окажетесь в ситуации что такого комбайна как VS code не будет под рукой?
Дважды в жизни мне приходилось экстренно - с телефона цепляться к боевому проекту по SSH с телефона, и подправлять косяки. В терминале, через nano.
Наличие хорошего инструмента - это прекрасно. Но он, к несчастью, не всегда будет с вами.
По крайней мере в С и C++ эта ошибка вымерла. Я пару лет назад статью на эту тему писал :)

Объявляю ошибку вида if (x = 42) вымирающей и заношу её в Красную книгу C и C++ багов
CVE всплывают то тут, то там, ошибки и баги могут быть разные, просто опечатку тоже лучше не исключать
когнитивная нагрузка в С языках всё еще выше, можно легко запутаться или что-то упустить
это как фортнайт + слушать музыку на фоне, паралельно книжку читать, и чтоб всё по таймингу и без помарок, учитывая кеш и прочие нюансы
А инструмента удобного нету, чтобы было минимум действий(под ключ скачал-запустил, и всё там уже настроено как нужно, без докачек и донастроек), постоянно что-то настраивать надо(тоесть всё надо буквально настраивать, ошибиться очень легко)
давайте настроим какой-нибудь инструмент, тулчейн, скрипт окружения, флаги компилятора, систему сборки, еще надо чо-то скачать настроить и возможно скомпилировать, сам дебагер тоже консольный подвержен командам и настройке
Линукс там еще бибилиотеки и прочее, да даже в винде хаос настроек
а что будет если вы оставите эту строку вам нужна скорость вы используете json stb sdl2 gl, и нечайно или по незнанию включите ffast-math?
тогда нстройка инструмента превратится в квест, нам нужна скорость и поддержка проверки infinity(строка в джейсоне 10832 - поидее эту проверку менять нельзя, значит надо сделать так чтоб у джейсона была проверка, что это как не то самое в виде настроек) и nan,
как следствие
Скрытый текст
cmake_minimum_required(VERSION 3.25)
project(EngineRPG LANGUAGES CXX)
# С++20 - золотая середина (стабильно и мощно) или 26
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# ПРИНУДИТЕЛЬНАЯ СТАТИКА (для vcpkg или системных либ)
set(BUILD_SHARED_LIBS OFF)
set(VCPKG_TARGET_TRIPLET x64-linux-static CACHE STRING "") # или x64-windows-static
# Поиск библиотек
find_package(SDL2 REQUIRED)
find_package(GLEW REQUIRED)
find_package(OpenGL REQUIRED)
# Флаги "Брони"
if(NOT MSVC)
add_compile_options(
-Wall -Wextra -Wpedantic -Wshadow -Wconversion
-fno-fast-math # Лечим бесконечность в JSON
-fstack-protector-strong # Защита от взлома
)
endif()
# СОБИРАЕМ ПРОЕКТ
# Добавляем файлы реализации JSON и STB сюда!
add_executable(EngineRPG
main.cpp
json_wrapper.cpp
stb_impl.cpp
# Persistency.cpp и другие...
)
# Линк
target_link_libraries(EngineRPG PRIVATE
GLEW::GLEW
OpenGL::GL
SDL2::SDL2
)
# Помечаем сторонние папки как SYSTEM (Игнорируем их мусор)
target_include_directories(EngineRPG SYSTEM PRIVATE
${SDL2_INCLUDE_DIRS}
${GLEW_INCLUDE_DIRS}
# Где лежит stb
. # Где лежит json
)
# Включаем LTO для максимального сжатия статики в один бинарник
include(CheckIPOSupported)
check_ipo_supported(RESULT lto_supported)
if(lto_supported)
set_target_properties(EngineRPG PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
что-то около такого файла, и из-за отсутствия агрессивной оптимизации что-то теряем(например скорость), тоесть квест усложняется буквально на каждом желании сохраняя скорость оставить и инфинити для джейсона и память, и скорость самого приложения
а мы же еще можем посмотреть в сторону vcpkg или Conan(можно еще докер поставить настроить вообще всё ради изоляции и безопасного отлова ошибок!) и квест станет еще гуще, и тогда переход на Раст это просто дело времени!
Автор: LLM, раздуй «Йода-сравнение» до длинного и круто выглядящего текста.
LLM:
Вместо if ($q = 2) мы пишем условие в инвертированном виде: if (2 = $q), и тем самым создаем логический парадокс машинного кода
Автор: Да нет, раздуй по-настоящему.
LLM:
в расте это как будто окончательно решили тем, что запретили = возвращать что либо кроме (). как по мне, само то, что присваивание возвращает ссылку является стрельбой в ногу, как и возможность типам быть конвертируемыми в bool кроме пары случаев когда тип действительно близок по смыслу навроде bool? в C# ну или, может быть, любых option-типов
следующий на очереди бул, потомучто проще u8 же, после раста я понял что это тип чисто с нюансами, он не весит 1 бит как я понимаю, это критически важно походу дела
Старый добрый Borland C++ 5 02 в таких случаях обязательно выдаёт предупреждение. В чём проблема то?
проблема как я считаю в общем, так-то конечно всё удобно,
Скрытый текст
clang++ -std=c++26 -O3 -ffast-math -msse4.2 -mavx2 main.cpp imgui/imgui.cpp imgui/imgui_draw.cpp imgui/imgui_widgets.cpp imgui/imgui_tables.cpp imgui/imgui_impl_sdl2.cpp imgui/imgui_impl_opengl3.cpp -o rgp_engine -I/usr/include/SDL2/ -lSDL2 -lGLEW -lGL
In file included from main.cpp:4:
In file included from ./Persistency.hpp:2:
./json.hpp:10832:31: warning: use of infinity is undefined behavior due to the currently enabled floating-point options [-Wnan-infinity-disabled]
10832 | ? std::numeric_limits<double>::infinity()
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
./json.hpp:12397:31: warning: use of infinity is undefined behavior due to the currently enabled floating-point options [-Wnan-infinity-disabled]
12397 | ? std::numeric_limits<double>::infinity()
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
./json.hpp:13321:51: warning: use of infinity is undefined behavior due to the currently enabled floating-point options [-Wnan-infinity-disabled]
13321 | if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
| ^~~~~~~~~~~~~~~~~~
./json.hpp:1689:94: note: expanded from macro 'JSON_HEDLEY_UNLIKELY'
1689 | # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
| ^~~~
./json.hpp:13151:13: note: in instantiation of function template specialization 'nlohmann::detail::parser<nlohmann::basic_json<>, nlohmann::detail::iterator_input_adapter<const char
*>>::sax_parse_internal<nlohmann::detail::json_sax_dom_callback_parser<nlohmann::basic_json<>, nlohmann::detail::iterator_input_adapter<const char *>>>' requested here
13151 | sax_parse_internal(&sdp);
| ^
./json.hpp:24306:148: note: in instantiation of member function 'nlohmann::detail::parser<nlohmann::basic_json<>, nlohmann::detail::iterator_input_adapter<const char *>>::parse' requested here
24306 | parser(detail::input_adapter(std::move(first), std::move(last)), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(true, result); // cppcheck-suppress[accessMoved]
| ^
./json.hpp:25520:28: note: in instantiation of function template specialization 'nlohmann::basic_json<>::parse<const char *>' requested here
25520 | return nlohmann::json::parse(s, s + n);
| ^
./json.hpp:13321:51: warning: use of infinity is undefined behavior due to the currently enabled floating-point options [-Wnan-infinity-disabled]
13321 | if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
| ^~~~~~~~~~~~~~~~~~
./json.hpp:1689:94: note: expanded from macro 'JSON_HEDLEY_UNLIKELY'
1689 | # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
| ^~~~
./json.hpp:13179:13: note: in instantiation of function template specialization 'nlohmann::detail::parser<nlohmann::basic_json<>, nlohmann::detail::iterator_input_adapter<const char
*>>::sax_parse_internal<nlohmann::detail::json_sax_dom_parser<nlohmann::basic_json<>, nlohmann::detail::iterator_input_adapter<const char *>>>' requested here
13179 | sax_parse_internal(&sdp);
| ^
./json.hpp:24306:148: note: in instantiation of member function 'nlohmann::detail::parser<nlohmann::basic_json<>, nlohmann::detail::iterator_input_adapter<const char *>>::parse' requested here
24306 | parser(detail::input_adapter(std::move(first), std::move(last)), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(true, result); // cppcheck-suppress[accessMoved]
| ^
./json.hpp:25520:28: note: in instantiation of function template specialization 'nlohmann::basic_json<>::parse<const char *>' requested here
25520 | return nlohmann::json::parse(s, s + n);
| ^
./json.hpp:19746:14: warning: use of infinity is undefined behavior due to the currently enabled floating-point options [-Wnan-infinity-disabled]
19746 | if (!std::isfinite(x))
| ^~~~~~~~~~~~~~~~
./json.hpp:19299:17: note: in instantiation of member function 'nlohmann::detail::serializer<nlohmann::basic_json<>>::dump_float' requested here
19299 | dump_float(val.m_data.m_value.number_float);
| ^
./json.hpp:21547:15: note: in instantiation of member function 'nlohmann::detail::serializer<nlohmann::basic_json<>>::dump' requested here
21547 | s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
| ^
./Persistency.hpp:42:18: note: in instantiation of member function 'nlohmann::basic_json<>::dump' requested here
42 | file << data.dump(4); // Красивый отступ
| ^
In file included from main.cpp:4:
In file included from ./Persistency.hpp:2:
./json.hpp:18911:17: warning: use of infinity is undefined behavior due to the currently enabled floating-point options [-Wnan-infinity-disabled]
18911 | JSON_ASSERT(std::isfinite(value));
| ^~~~~~~~~~~~~~~~~~~~
./json.hpp:2575:35: note: expanded from macro 'JSON_ASSERT'
2575 | #define JSON_ASSERT(x) assert(x)
| ^
/usr/include/assert.h:100:27: note: expanded from macro 'assert'
100 | (static_cast <bool> (expr) \
| ^~~~
./json.hpp:19767:41: note: in instantiation of function template specialization 'nlohmann::detail::to_chars<double>' requested here
19767 | auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
| ^
./json.hpp:19761:9: note: in instantiation of member function 'nlohmann::detail::serializer<nlohmann::basic_json<>>::dump_float' requested here
19761 | dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
| ^
./json.hpp:19299:17: note: in instantiation of member function 'nlohmann::detail::serializer<nlohmann::basic_json<>>::dump_float' requested here
19299 | dump_float(val.m_data.m_value.number_float);
| ^
./json.hpp:21547:15: note: in instantiation of member function 'nlohmann::detail::serializer<nlohmann::basic_json<>>::dump' requested here
21547 | s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
| ^
./Persistency.hpp:42:18: note: in instantiation of member function 'nlohmann::basic_json<>::dump' requested here
42 | file << data.dump(4); // Красивый отступ
| ^
In file included from main.cpp:4:
In file included from ./Persistency.hpp:2:
./json.hpp:18736:17: warning: use of infinity is undefined behavior due to the currently enabled floating-point options [-Wnan-infinity-disabled]
18736 | JSON_ASSERT(std::isfinite(value));
| ^~~~~~~~~~~~~~~~~~~~
./json.hpp:2575:35: note: expanded from macro 'JSON_ASSERT'
2575 | #define JSON_ASSERT(x) assert(x)
| ^
/usr/include/assert.h:100:27: note: expanded from macro 'assert'
100 | (static_cast <bool> (expr) \
| ^~~~
./json.hpp:18944:16: note: in instantiation of function template specialization 'nlohmann::detail::dtoa_impl::grisu2<double>' requested here
18944 | dtoa_impl::grisu2(first, len, decimal_exponent, value);
| ^
./json.hpp:19767:41: note: in instantiation of function template specialization 'nlohmann::detail::to_chars<double>' requested here
19767 | auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
| ^
./json.hpp:19761:9: note: in instantiation of member function 'nlohmann::detail::serializer<nlohmann::basic_json<>>::dump_float' requested here
19761 | dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
| ^
./json.hpp:19299:17: note: in instantiation of member function 'nlohmann::detail::serializer<nlohmann::basic_json<>>::dump_float' requested here
19299 | dump_float(val.m_data.m_value.number_float);
| ^
./json.hpp:21547:15: note: in instantiation of member function 'nlohmann::detail::serializer<nlohmann::basic_json<>>::dump' requested here
21547 | s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
| ^
./Persistency.hpp:42:18: note: in instantiation of member function 'nlohmann::basic_json<>::dump' requested here
42 | file << data.dump(4); // Красивый отступ
| ^
In file included from main.cpp:4:
In file included from ./Persistency.hpp:2:
./json.hpp:18034:17: warning: use of infinity is undefined behavior due to the currently enabled floating-point options [-Wnan-infinity-disabled]
18034 | JSON_ASSERT(std::isfinite(value));
| ^~~~~~~~~~~~~~~~~~~~
./json.hpp:2575:35: note: expanded from macro 'JSON_ASSERT'
2575 | #define JSON_ASSERT(x) assert(x)
| ^
/usr/include/assert.h:100:27: note: expanded from macro 'assert'
100 | (static_cast <bool> (expr) \
| ^~~~
./json.hpp:18758:26: note: in instantiation of function template specialization 'nlohmann::detail::dtoa_impl::compute_boundaries<double>' requested here
18758 | const boundaries w = compute_boundaries(value);
| ^
./json.hpp:18944:16: note: in instantiation of function template specialization 'nlohmann::detail::dtoa_impl::grisu2<double>' requested here
18944 | dtoa_impl::grisu2(first, len, decimal_exponent, value);
| ^
./json.hpp:19767:41: note: in instantiation of function template specialization 'nlohmann::detail::to_chars<double>' requested here
19767 | auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
| ^
./json.hpp:19761:9: note: in instantiation of member function 'nlohmann::detail::serializer<nlohmann::basic_json<>>::dump_float' requested here
19761 | dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
| ^
./json.hpp:19299:17: note: in instantiation of member function 'nlohmann::detail::serializer<nlohmann::basic_json<>>::dump_float' requested here
19299 | dump_float(val.m_data.m_value.number_float);
| ^
./json.hpp:21547:15: note: in instantiation of member function 'nlohmann::detail::serializer<nlohmann::basic_json<>>::dump' requested here
21547 | s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
| ^
./Persistency.hpp:42:18: note: in instantiation of member function 'nlohmann::basic_json<>::dump' requested here
42 | file << data.dump(4); // Красивый отступ
| ^
In file included from main.cpp:4:
In file included from ./Persistency.hpp:2:
./json.hpp:13321:51: warning: use of infinity is undefined behavior due to the currently enabled floating-point options [-Wnan-infinity-disabled]
13321 | if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
| ^~~~~~~~~~~~~~~~~~
./json.hpp:1689:94: note: expanded from macro 'JSON_HEDLEY_UNLIKELY'
1689 | # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
| ^~~~
./json.hpp:13151:13: note: in instantiation of function template specialization 'nlohmann::detail::parser<nlohmann::basic_json<>,
nlohmann::detail::input_stream_adapter>::sax_parse_internal<nlohmann::detail::json_sax_dom_callback_parser<nlohmann::basic_json<>, nlohmann::detail::input_stream_adapter>>' requested here
13151 | sax_parse_internal(&sdp);
| ^
./json.hpp:24470:42: note: in instantiation of member function 'nlohmann::detail::parser<nlohmann::basic_json<>, nlohmann::detail::input_stream_adapter>::parse' requested here
24470 | parser(detail::input_adapter(i)).parse(false, j);
| ^
./Persistency.hpp:51:10: note: in instantiation of member function 'nlohmann::operator>>' requested here
51 | file >> data;
| ^
In file included from main.cpp:4:
In file included from ./Persistency.hpp:2:
./json.hpp:13321:51: warning: use of infinity is undefined behavior due to the currently enabled floating-point options [-Wnan-infinity-disabled]
13321 | if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
| ^~~~~~~~~~~~~~~~~~
./json.hpp:1689:94: note: expanded from macro 'JSON_HEDLEY_UNLIKELY'
1689 | # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
| ^~~~
./json.hpp:13179:13: note: in instantiation of function template specialization 'nlohmann::detail::parser<nlohmann::basic_json<>,
nlohmann::detail::input_stream_adapter>::sax_parse_internal<nlohmann::detail::json_sax_dom_parser<nlohmann::basic_json<>, nlohmann::detail::input_stream_adapter>>' requested here
13179 | sax_parse_internal(&sdp);
| ^
./json.hpp:24470:42: note: in instantiation of member function 'nlohmann::detail::parser<nlohmann::basic_json<>, nlohmann::detail::input_stream_adapter>::parse' requested here
24470 | parser(detail::input_adapter(i)).parse(false, j);
| ^
./Persistency.hpp:51:10: note: in instantiation of member function 'nlohmann::operator>>' requested here
51 | file >> data;
| ^
10 warnings generated.
предупреждений может быть больше, и всё вместе в композиции выглядит удачно


Инвертирование равенства. Как реже стрелять себе в ногу в C-подобных языках