Гарантируется ли, что поразрядно "а" для bool не закорачивается? - PullRequest
0 голосов
/ 08 января 2019

Недавно я наткнулся на фрагмент кода, который выглядел так:

bool MyClass::do_work()
{
    bool success = true;
    for (auto const& worker : m_workers)
    {
        success &= worker.do_work();  // worker.do_work() returns a bool
    }
    return success;
}

Если я правильно понимаю, функция возвращает true, если все работники возвращают true, и возвращает false, если какой-либо работник возвращает false. Тем не менее, он всегда оценивает всех работников (что желательно). Оценка короткого замыкания не требуется, поскольку использовался побитовый оператор &=, а не логический оператор &&.

Это поведение гарантировано? Точнее, гарантируется ли, что поразрядное & всегда вычисляет оба операнда, даже если они имеют тип bool? Я встречал много ответов SO относительно гарантированной оценки короткого замыкания для &&, но ни один из них не утверждал, что есть гарантированная оценка без короткого замыкания для &.

Если это поведение гарантировано, это хороший стиль программирования? Мне потребовалось больше, чем быстрый взгляд, чтобы понять функцию, потому что я раньше не видел этот стиль, и сначала я был озадачен, была ли включена оценка короткого замыкания или нет.

Есть ли лучшая альтернатива, чем следующая?

bool MyClass::do_work()
{
    bool success = true;
    for (auto const& worker : m_workers)
    {
        if (!worker.do_work())
        {
            success = false;
        }
    }
    return success;
}

1 Ответ

0 голосов
/ 08 января 2019

Если явно не указано в стандарте, все операнды оператора оцениваются и не упорядочиваются 1 в C ++:

[intro.execution]

За исключением отмеченных случаев, оценки операндов отдельных операторов и подвыражений отдельных выражений не являются последовательными. [...] Вычисления значений операндов оператора секвенируются до вычисления значения результата оператора. [...]

Мне на ум приходят только три исключения: операторы &&, || и ?: 2 .

Стандартное четное упоминание для && 3 , что:

[expr.log.and]

В отличие от &, && гарантирует вычисление слева направо: второй операнд не оценивается, если первый операнд false.

А если это хороший стиль программирования, то он основан на мнении.


1 Unsequenced в основном означает, что если у вас есть A @ B (где @ - оператор), B (и его побочные эффекты) могут быть оценены до A, вот почему такие конструкции, как i++ + ++i имеют неопределенное поведение .

2 Обратите внимание, что для перегруженных операторов && и || это больше не так, поскольку оба операнда вычисляются. ?: не может быть перегружен.

3 Аналогичная заметка для | в [expr.log.or] .

...