TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.35K subscribers
Post #202 2.22K
​Бинарные логические операторы. Short circuit.

Хотел прояснить один момент. В этом посте я сказал, что при инстанциации шаблонов операторы && и || не могут похвастаться наличием короткой схемы, в том числе в виде fold expression. Я имел ввиду, что вам придется конкретизировать все метаклассы(ну не прям вам своими ручками, но тем не менее) для того, чтобы начать вычислять выражение. Это правда, без сомнений.

Однако я понял, что некоторые из наших дорогих подписчиков возможно могли сконфузится конфузом, что тут я говорю, что короткой схемы у них нет, а в посте про вычисления по короткой схеме я ставлю в пример эти два оператора. Вроде бы противоречие. Но нет. Тут довольно тонкая грань.

Опять же, без сомнений, && и || что в обычном виде, что в форме fold expression выполняют вычисления по короткой схеме. Они просто обязаны инстанциировать все шаблонные параметры/параметры из пака шаблонных аргументов, чтобы начать выполняться и начать проявлять свои short circuit свойства. То есть

template <class T>
struct type_without_value
{
};

template <class T1, class T2>
constexpr auto numbers = (std::is_integral_v<T1> && type_without_value<T2>::value);

constexpr auto result = numbers<float, int>;


вот этот пример крашнется на компиляции, потому что компилятору нужно инстанцировать type_without_value<T2> и достать из него value, но он не сможет этого сделать, потому что type_without_value не содержит члена value. Но в случае удачной инстанциации этот пример:

template <class T1, class T2>
constexpr auto numbers = (std::is_integral_v<T1> && std::is_integral_v<T2>);

constexpr auto result = numbers<float, int>;


успешно соберется и result будет равен false, как и ожидается. В этом случае значение правого операнда учитываться не будет.

Это можно продемонстрировать на следующем примере. Вот такой код успешно соберется и выполнится:

constexpr bool is_even(int value) noexcept {
return (value % 2 == 0) ? true : throw std::logic_error("Don't throw me around, you bastard!");
}

template <class T>
constexpr auto numbers = (std::is_integral_v<T> && is_even(1));

constexpr auto result = numbers<float>;
// constexpr bool fail = is_even(1);


Как видите, при выполнении функции is_even, если в нее попадет нечетное число, то бросится исключение. Исключение, брошенное в compile-time, прерывает компиляцию.

Но в крайнем примере все пройдет хорошо, потому что is_even ни разу не выполнится, как раз из-за короткосхемности оператора &&!

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

Вот такие дела. Надеюсь, я не зря волновался и для кого-то получше прояснил ситуацию.

Explain things clearly. Stay cool.

#template #compiler
  • 🔥 8
  • 👍 6
  • ❤ 4
  • 🤯 3
More from @grokaemcpp
  1. Oct 17, 2026​​Оптимистичные и пессимистичные блокировки #опытным Концепция блокировок уходит далеко за…
  2. Oct 14, 2026​​Что внутри std::condition_variable? #опытным Более менее все знакомы с примитивом синхро…
  3. Oct 12, 2026​​WAT #новичкам Как вы думаете, результат выражения: bool math = -1 < 1U; будет правдой ил…
  4. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  5. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  6. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
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 →