Всегда, после прочтения Ваших статей, возникает желание пересмотреть свой код на наличие подобных ошибок.
Распространённой ошибкой при программировании является, когда одна и та же проверка выполняется дважды.
Подобное встречаю часто, вот недавно нарвался в хранимке постгреса, внутренняя процедура для обслуживания таблиц и схем:

SELECT 'GRANT '
        || (CASE
                WHEN (c.gr = 'a') THEN 'INSERT'
                WHEN (c.gr = 'r') THEN 'SELECT'
                WHEN (c.gr = 'w') THEN 'UPDATE'
                WHEN (c.gr = 'r') THEN 'SELECT'    -- <<< тут
                WHEN (c.gr = 'D') THEN 'TRUNCATE'
                WHEN (c.gr = 'x') THEN 'REFERENCES'
                WHEN (c.gr = 't') THEN 'TRIGGER'
            END)


Второй хуже: хотели проверить какие-то другие переменные, но опечатались.
Именно второй, результатом copy/paste стал пропуск этого кейса:

WHEN (c.gr = 'd') THEN 'DELETE'
У меня, скорее всего, что-то подобное с логикой MTP и PTP на телефоне. Фотографии копируются идеально, пока у них не появляются 'сателлиты' с одинаковым временем съемки и датой, отличающейся всего на одну цифру в дне. Как только это случается, телефон отдает более свежую фотографию под более старым именем.
Похоже, что проверка на NaN просто лишняя и код можно сократить до

а вдруг идея проверки в том, что NaN не должен быть равен другому NaN. Иначе зачем вообще заводить метод сравнения, если можно обойтись штатным оператором сравнения ==?

В целом, очень не люблю «почти полностью» повторяющиеся куски кода. Как раз из-за повышенного требования к внимательности в процессе их написания. Сравнения, особенно лексикографические, лучше делать через std::tie.
NaN всегда неравен NaN.
вот только сегодня допустил такую же ошибку в коде. Сравнил одну переменную с собой. Юнит-тесты, однако, не стали этого от меня скрывать и половина из них попадала. В преведённых выше проектах видать юнит тестами не пользуются или только в крайних случаях
Для себя придумал следующий способ избежать подобных проблем. Внутри класса заводим метод что-нибудь вроде asTuple. Закидываем в кортеж все необходимые значения и сравниваем кортежи лексикографически (что уже есть из коробки). PROFIT

А можно было бы просто выводить (derive) реализации таких функций автоматически, по премеру Haskell и Rust.

А метод asTuple настолько прост, что… Ну, вы поняли.

Этот метод, прежде всего, будет частоиспользуемый. Ошибки подобного рода обычно "спят" в редкоиспользуемых ветках программы.

то, что класс предоставляет какой-либо метод, отнюдь не значит, что он будет часто использоваться
Можно не совсем по теме? Что это за паттерн такой использовать "--size"?
Оно?

while ( --size >= 0 ){

Паттерны тут не при чём, это просто код, который делает вполне определённые вещи: сначала декремент, потом проверку условия.
Ой, вот это я дал, вспомнилось !!bool_var; и подумал что это двойное отрицание.
Кстати, где-то видел вот такой эстетически красивый вариант:
while (size-->0) {
Ага. К сожалению, в примере из статьи и он не будет работать, если при входе в цикл size уже 0.
Интересно, почему ещё не было придумано синтаксического сахара, который бы позволял написать что-то вроде этого:
myClass obj1;
myClass obj2;
...

foreach(classField field in myClass{foo,bar,baz}) {
  if (obj1.field != obj2.field) return false
}
return true;

?

Поэтому в таких случаях стоит пользоваться кодогенерацией. Если она есть из коробки как в Rust, так вообще прекрасно.

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