TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.35K subscribers
Post #324 3.93K
​​Short circuit для кастомных операторов
#опытным

Есть одно важное уточнение, которое не было упомянуто в посте про short-circuit операторы, но несколько комментаторов на это указывали. Прочитайте, кстати, пост, если впервые видите словосочетание short circuit.

В плюсах короткосхемностью обладают операторы && и ||. Из коробки их операндами могут быть переменные логического, целочисленного и указательного типа. Однако они все так или иначе приводятся к типу булеан. Поэтому в принципе корректно говорить, что логические операторы работают только с логическими типами. Что в целом довольно логичная логика.

Однако есть в этом Эдеме есть и змий искуситель, который портит всю малину. Эти операторы можно перегружать для кастомных типов. И тогда они теряют свои короткосхемные свойства.

Взгляните на следующий код:


struct CustomStruct
{
int number = 0;
bool operator&&(const CustomStruct& other)
{
return number && other.number;
}
};

static int check = 0;

CustomStruct func()
{
check = 1;
return CustomStruct{};
}

int main() {
CustomStruct a{};
a && func();
std::cout << check << std::endl;
}


Здесь мы создаем самую простую структурку и перегружаем для нее оператор логического И. Дальше, чтобы проверить ленивость вычисления оператора, пишем простую функцию, которая при исполнении изменяет статическую переменную. Так мы сможем наверняка убедиться, выполнилась ли функция или нет: если выполнилась, то переменная check будет выставлена в единицу, если нет, то останется нулем.

И вывод будет реально "1". Что выглядит довольно печально.

Ну и кстати, такое поведение довольно легко объяснить. Когда мы перегружаем операторы, то мы создаем новые функции. И я хочу акцентировать на этом внимание: это именно пользовательские функции, как бы они там не назывались. А аргументы пользовательских функций должны быть вычислены ДО захода в функцию. Поэтому любые операнды должны быть полностью вычислены до вычисления значения всего выражения. Это и приводит к отсутствию свойства short circuit.

Хотя в том виде, в котором оператор перегружен в коде выше, внутри него используется short circuit операция и на самом деле второй операнд не будет учитываться, если у вызываемого объекта поле класса равно нулю. Но за счет того, что мы обязаны вычислить второй операнд, то просто технически не выполняются требования короткой схемы вычислений.

Встроеные же операторы реализованы на более низком уровне и не являются в прямом смысле функциями. И в эту реализацию изначально заложен короткосхемный функционал.

Однако есть способ разрешить ленивое вычисление логического И или ИЛИ для кастомных типов. Но об этом в следующий раз.

Don't loose your properties. Stay cool

#cppcore
  • 🔥 16
  • 👍 9
  • ⚡ 3
  • ❤ 2
  • 💯 1
More from @grokaemcpp
  1. Oct 14, 2026​​Что внутри std::condition_variable? #опытным Более менее все знакомы с примитивом синхро…
  2. Oct 12, 2026​​WAT #новичкам Как вы думаете, результат выражения: bool math = -1 < 1U; будет правдой ил…
  3. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  4. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  5. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  6. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →