Ответ 1
Компилятор находится справа. Давайте проанализируем типы, связанные с вашими двумя if
s, принимая во внимание все операторы которые boost::tribool
предоставляет:
if (tmp && (boo = should_not_be_called ()) == false) {;}
if (bool && (tribool = bool) == bool) {;} // = is overloaded to return tribool
if (bool && tribool == bool) {;} // == is overloaded to return tribool
if (bool && tribool) {;} // && is overloaded
И второй if
:
if (tmp && (false == (boo = should_not_be_called ()))) {;}
if (bool && (bool == (tribool = bool))) {;} // = is overloaded to return tribool
if (bool && (bool == tribool)) {;} // == is overloaded to return tribool
if (bool && tribool) {;} // && is overloaded
В обоих случаях мы получаем перегруженный operator &&
. Перегрузки операторов - это функции, которые не учитывают поведение специальных вызовов встроенных операторов. То есть пользовательский перегруженный &&
, ||
делает не короткое замыкание, а пользовательские перегрузки ,
делают не гарантированный порядок оценки операнда. Все три оценивают все их операнды в неуказанном порядке, как и любой другой вызов функции.
Именно по этой причине настоятельно не рекомендуется перегружать &&
, ||
или ,
, если вы хотите, чтобы они имели в виду нечто вроде "и", "или" и "последовательность".
Выдержка из оригинального текста вопроса:
Компилятор находится справа. boost::tribool
перегрузки opeator !
, что означает, что типы операндов &&
равны bool
и boost::tribool
. boost::tribool
также перегружает operator &&
для этих типов аргументов, поэтому эта перегрузка вызывается.