Недавно я использовал boost::logic::tribool
и что-то было для меня странным.
#include <iostream>
#include "boost/logic/tribool.hpp"
int main()
{
boost::logic::tribool test = true && boost::logic::indeterminate;
if (test)
{
std::cout << "Executes?" << std::endl;
}
if (true && boost::logic::indeterminate)
{
std::cout << "Executes 2" << std::endl;
}
}
Печатает Executes
и Executes 2
.
Почему эти условия верны?
Я был полностью уверен, что операция И с (неопределенное состояние, истина) возвращает неопределенное состояние?
Цитата с сайта boost.org о логическом контексте в if
"возвращает true, если логическое значение с тремя состояниями истинно, иначе - false"
Обновлено: после комментариев я добавляю это. Это самый неинтуитивный код, который я когда-либо читал.
#include <iostream>
#include "boost/logic/tribool.hpp"
int main()
{
boost::logic::tribool test = boost::logic::tribool(true) && boost::logic::indeterminate;
if (test)
{
std::cout << "This will NOT execute" << std::endl;
}
boost::logic::tribool second = true && boost::logic::indeterminate;
if (second)
{
std::cout << "This will execute" << std::endl;
}
}
EDIT2: мне нужно исправить себя... Кто-нибудь может объяснить?
#include <iostream>
#include "boost/logic/tribool.hpp"
boost::logic::tribool LOL( )
{
return boost::logic::indeterminate;
}
int main()
{
boost::logic::tribool LOL_RESULT = LOL();
if (boost::logic::indeterminate)
{
std::cout << "IT WILL BE EXECUTED" << std::endl;
}
if (LOL_RESULT)
{
std::cout << "IT WILL NOT BE EXECUTED" << std::endl;
}
}
Но почему все-таки это правда?
Понятия не имею... из любопытства: для чего вы его используете? Даже без этой причуды я нахожу это tribool
очень запутанным и не хотел бы иметь его в своем коде. Я имею в виду, что может быть более странным, чем логическое преобразование, так что после if (b) {} else if (!b) {}
у вас все еще есть else {}
case... имхо, это неявное преобразование зашло слишком далеко
Вам не нужно меня убеждать, большая кодовая база, вы знаете, много странных людей и идей может появиться на протяжении всей жизни большого проекта.
хорошо, без проблем, документация немного небрежна: boost.org/doc/libs/1_59_0/doc/html/boost/logic/… Обратите внимание, что в ней говорится «результат логического И с два значения трибула в соответствии со следующей таблицей:», что, строго говоря, исключает перегрузку (bool,tribool)
C++ не поддерживает трехзначную логику, а оператор if ()
является конструкцией языка C++, а не частью boost::logic::tribool
. Любое значение, которое преобразуется во что-то отличное от целого числа, равного нулю, nullptr
или false
, будет рассматриваться оператором if ()
как истинное. И это, очевидно, включает boost::logic::indeterminate
.
@cmaster, если я правильно понимаю их основной пример, то, что вы говорите, неверно. tribool
имеет очень причудливое логическое преобразование, которое может сделать как b
, так и !b
false
одновременно, именно тогда, когда значение равно indeterminate
@formerlyknownas_463035818 А вы уверены, что значение действительно конвертируется в bool
? Я не знаю boost::logic
, но если оператор if (boost::logic::indeterminate) foo();
выполняет foo()
, то значение не может быть преобразовано в false
. Может баг, может ловушка, не знаю какая.
@cmaster хм? if (boost::logic::indeterminate) foo();
не выполняется foo();
. Я не вникал во все детали, но в основном все, что вам нужно, это operator bool
и operator!
, тогда вы можете заставить if (indeterminate) {
bar();} else if (! indeterminate) {
bar();} else { foo();}
выполнять только foo();
, но не bar();
TEST(junk, tribool)
{
auto v = boost::logic::indeterminate;
GTEST_MESSAGE() << typeid(v).name();
}
Результат:
[----------] 1 test from junk
[ RUN ] junk.tribool
[ NOTE ] bool (__cdecl*)(class boost::logic::tribool,struct boost::logic::detail::indeterminate_t)
boost::logic::indeterminate
это функция. Таким образом, он оценивается как истинный.
TEST(junk, tribool)
{
boost::logic::tribool test = true && boost::logic::tribool{ boost::logic::indeterminate_keyword_t() };
if (test)
{
GTEST_MESSAGE() << "Executes?" << std::endl;
}
if (true && boost::logic::tribool{ boost::logic::indeterminate_keyword_t() })
{
GTEST_MESSAGE() << "Executes 2" << std::endl;
}
}
Результат:
[----------] 1 test from junk
[ RUN ] junk.tribool
[ OK ] junk.tribool (64970 ms)
[----------] 1 test from junk (68580 ms total)
Обратите внимание, что вы получаете ожидаемый результат для
boost::logic::tribool test = boost::logic::tribool{true} && boost::logic::indeterminate;