Руководство по разработке Boost-4.7tribool

трибул

boost.tribool похож на встроенный тип bool в C++, но основан на логической логике с тремя состояниями: помимо true (истина) и false (ложь), существует неопределенное состояние (неизвестно, неопределенно). Пример сценария - выполнение определенной задачи. Статус до выполнения неизвестен (нет начала и конца). После запуска задачи статус true, а после остановки задачи статус false.

Tribool расположен в пространстве имен boost::logic, но для удобства использования пространство имен boost вводится оператором using. Чтобы использовать компонент tribool, вам необходимо включить заголовочный файл <boost/logic/tribool. hpp>, то есть

#include <boost/logicltribool.hpp>
using namespace boost;

Краткое описание класса

class tribool
{
    
    
public:
   tribool(bool value); //缺省构造函数
   tribool(bool initial_value); //bool值构造函数
   tribool (indeterminate_keyword_t); //初始化为不确定值
   operator safe_bool() const; //bool转型
   enum value_t {
    
     false_value,true_value,indeterminate_value } value;
};
bool indeterminate (tribool x); //判断是否是不确定状态
tribool operator!(tribool x);
... //其他逻辑运算符和比较运算符重载

Класс tribool очень простой, внутри он реализует представление логических значений с тремя состояниями и не имеет других функций-членов, кроме конструктора. Вы можете инициализировать объект tribool, передав ему значение bool с тремя состояниями при его создании. Если вы используете конструктор по умолчанию без параметров, значение по умолчанию для tribool равно false.

Операции над tribool выполняются путем перегрузки логических операторов и операторов сравнения. Поддерживаемые логические операции включают ||, && и !, а операции сравнения поддерживают == и !=. Эти операции могут произвольно смешивать операции bool и Tribool вместе.

Неопределенное состояние неопределенного значения представляет собой специальное трибулевое значение. Его работа с логическими значениями true и false следует логической логике с тремя состояниями: 1) Результат любой операции сравнения с
неопределенным значением является неопределенным;
2) Логическая операция ИЛИ с неопределенным значением. (|| ) Только результат операции с истиной является истиной,
а остальные все неопределенные; 3) Логическая операция И (&&) с неопределенным имеет только результат операции с ложью, а остальные неопределенные;
4 ) Результат логической операции НЕ (!) неопределенного по-прежнему остается неопределенным.

Применение

Tribool можно использовать как обычный тип bool, за исключением того, что он имеет дополнительное неопределенное (неизвестное, неопределенное) значение. Если используются только два значения true и false, использование tribool и bool точно такое же, но если вам нужно использовать неопределенное значение, вы должны следовать правилам логической работы логического значения с тремя состояниями.

#include <boost/logic/tribool.hpp>
using namespace boost;
int main()
{
    
    
	tribool tb(true); //值为true的tribool
	tribool tb2(!tb); //值为false

	if (tb) //tb==true
	{
    
    
		cout << "true" << endl;
	}

	tb2 = indeterminate; //tb2是不确定状态
	assert(indeterminate(tb2)); //用indeterminate函数检测状态
	cout << "tb2 = " << tb2 << endl;

	if (tb2 == indeterminate) //与indeterminate值比较,无意义
	{
    
    
		cout << "indeterminate" << endl; //这行语句不会执行
	}

	if (indeterminate(tb2)) //用indeterminate函数检测状态
	{
    
    
		cout << "indeterminate" << endl; //输出"indeterminate"
	}

	cout << (tb2 || true) << endl; //逻辑或运算,输出true
	cout << (tb2 && false) << endl; //逻辑与运算,输出false
}

Вы должны быть осторожны при работе с неопределенным состоянием трибула, потому что оно не является ни истинным, ни ложным. Использование его для вынесения условных суждений никогда не будет установлено. Чтобы судить о неопределенном состоянии, вы должны использовать функцию indeterminate():

tribool tb(indeterminate);

if (tb) //永远不成立
	cout << "never reach here" << endl;
if (!tb) //永远不成立
	cout << "never reach here" << endl;

if (indeterminate(tb)) //必须使用indeterminate
	cout << "indeterminate" << endl;

Переименуйте третье состояние

Третий тип состояния indeterminate_keyword_t в tribool на самом деле является типом указателя функции:

typedef bool(*indeterminate_keyword_t) (tribool,detail::indeterminate_t);

Indeterminate на самом деле — это просто функция, которая соответствует типу indeterminate_keyword_t. Ее реальная функция — определить, находится ли внутреннее значение объекта tribool в третьем состоянии, но она используется как флаг в конструкторе tribool. Пока это так типа indeterminate_keyword_t, ему присвоен статус Неопределенный:

tribool(indeterminate_keyword_t) : //构造函数,接受特殊的参数
           value (indeterminate_value){
    
    } //置为不确定状态

В качестве третьего состояния неопределенное имя очень понятно, но может быть немного длинным, поэтому tribool позволяет заменить неопределенное имя на любое имя, которое нравится пользователю. Часто используемые имена могут быть неизвестными, например, true_or_false и т. д.

Вам нужно всего лишь использовать макрос BOOST_TRIBOOL_THIRD_STATE в глобальной области видимости, чтобы переименовать третье состояние, например:

BOOST_TRIBOOL_THIRD_STATE(unknown)

Затем мы можем использовать это новое имя вместо исходного неопределенного:

tribool tb(unknown); //可以作为不确定值
assert(unknown(tb)); //可以作为检测函数
assert(unknown(tb || false));

Макрос BOOST_TRIBOOL_THIRD_STATE просто определяет новую функцию типа indeterminate_keyword_t, похожую на:

inline bool some_name(tribool x)
{
    
     return x.value == tribool::indeterminate_value; }

Поскольку макрос BOOST_TRIBOOL_THIRD_STATE по сути определяет функцию, а C++ не допускает вложенности функций, этот макрос лучше всего использовать в глобальной области, и после определения он вступит в силу во всем исходном коде.

Если BOOST_TRIBOOL_THIRD_STATE используется в пространстве имен, новое имя третьего состояния станет членом пространства имен, и при его использовании необходимо добавить уточнения пространства имен, например:

namespace tmp_ns //一个临时名字空间
{
    
    
    BOOST_TRIBOOL_THIRD_STATE(unknown)
};
tribool tb (tmp_ns::unknown); //使用名字空间限定

ввод, вывод

Tribool может выполнять потоковые операции, такие как тип bool, но должен включать еще один файл заголовка <boost/logic/tribool_io.hpp>

Пока этот заголовочный файл включен, вы можете использовать операторы >> и << для ввода/вывода потоковых объектов, таких как cin и cout. false, true и indeterminate соответствуют целым числам 0, 1 и 2 соответственно. Если установлен флаг boolalpha потока, он соответствует строкам «false», «true» и «indeterminate».

#include<boost/logic/tribool_io.hpp>
using namespace boost;
int main()
{
    
    
    tribool tb1(true),tb2(false),tb3(indeterminate);
    cout << tb1 << "," //输出1
         << tb2 << "," //输出0
         << tb3 << endl; //输出2
}

optional<bool>Разница между

optional<bool>По функции несколько похоже на трибул, неинициализированный optional<bool>может также представлять неопределенное логическое значение, например:

optional<bool> b;
if(!b) //b未初始化,既不是true也不是false
{
    
     cout << "indeterminate" << endl; }

b = false;
if(b) //b有值false
{
    
     cout << "b=" << *b << endl; } 

Но optional<bool>семантика такова, что неинициализированное логическое значение является бессмысленным значением, в то время как неопределенное значение трибула является инициализированным значимым значением, что означает, что значение логического типа является неопределенным. Есть тонкое, но важное различие.

Кроме того, существуют различия в способах их использования. optional<bool>Для доступа к значению bool в контейнере необходимо использовать метод, подобный указателю, а tribool можно использовать напрямую, как обычный тип bool, и он поддерживает различные логические операции.

Поскольку необязательный поддерживает преобразование bool, которое используется для определения того, был ли инициализирован необязательный параметр, если вы не обратите внимание на эту особенность необязательного параметра в контексте bool, это может легко привести к неожиданным ошибкам. Например, следующий код предназначен для использования значения bool в необязательном параметре в качестве условия определения оператора if, но на самом деле условие определяет, что необязательный параметр не инициализирован:

optional<bool> b(false);
if(!b) //optional的bool转换
{
    
     cout << "false" << endl; }

Правильный способ написания должен быть

if(b && !*b) //b已经初始化且值为false
{
    
     cout << "false" << endl; } 

Выбор между трибулом optional<bool>и трибулом должен определяться конкретными потребностями кода. Если возвращаемое значение может быть недействительным (действительного возвращаемого значения не существует), тогда да optional<bool>; если возвращаемое значение всегда достоверно, но его значение не может быть определено, тогда используйте tribool.

пример кода

#include <assert.h>
#include <iostream>
using namespace std;

#include <boost/logic/tribool.hpp>
#include <boost/logic/tribool_io.hpp>
using namespace boost;

//
void case1()
{
    
    
	tribool tb(true);
	tribool tb2(!tb);

	if (tb)
	{
    
    
		cout << "true" << endl;
	}

	tb2 = indeterminate;
	assert(indeterminate(tb2));
	cout << "tb2 = " << tb2 << endl;

	if (tb2 == indeterminate)
	{
    
    
		cout << "indeterminate" << endl;
	}

	if (indeterminate(tb2))
	{
    
    
		cout << "indeterminate" << endl;
	}

	cout << (tb2 || true) << endl;
	cout << (tb2 && false) << endl;

}

//
void case2()
{
    
    
	tribool tb(indeterminate);

	if (tb)
		cout << "never reach here" << endl;
	if (!tb)
		cout << "never reach here" << endl;

	if (indeterminate(tb))
		cout << "indeterminate" << endl;
}

//
BOOST_TRIBOOL_THIRD_STATE(unknown)

namespace tmp_ns
{
    
    
	BOOST_TRIBOOL_THIRD_STATE(unknown)
};


void case3()
{
    
    
	tribool tb(tmp_ns::unknown);
	assert(unknown(tb));
	assert(unknown(tb || false));

}

//
#include <boost/optional.hpp>
using namespace boost;

void case4()
{
    
    
	optional<bool> b;

	if (!b)
	{
    
    
		cout << "indeterminate" << endl;
	}

	b = false;
	if (b)
	{
    
    
		cout << "b=" << *b << endl;
	}

	if (!b)
	{
    
    
		cout << "false" << endl;
	}

	if (b && !*b)
	{
    
    
		cout << "real false" << endl;
	}

}

//

int main()
{
    
    
	case1();
	case2();
	case3();
	case4();
}

Вставьте сюда описание изображения

рекомендация

отblog.csdn.net/qq_36314864/article/details/132333744