Ответ 1
Я не знаю общепринятой библиотеки утилиты, которая обеспечивает идиому safe-bool. В Boost было несколько попыток, и они часто приводят к дебатам о том, как обеспечить реализацию safe-bool (соглашения об именах, макросы, встроенные вложения, наследование). В результате в Boost существует не менее трех реализаций, только с одной из реализаций, Boost.Spirit.Classic safe_bool, предназначенных для внешних использовать.
Подробности и концепции для каждой реализации:
- Boost.Range safe_bool
- Содержится в каталоге подробностей, поэтому он явно не предназначен для внешнего использования.
- Реализовано с использованием вспомогательного типа шаблона и статических функций-членов.
- Ожидается, что класс с поддержкой safe-bool:
- Предоставить функцию члена
operator boost::range_detail::safe_bool< MemberPtr >::unspecified_bool_type() const
, которая делегирует статическую функциюsafe_bool::to_unspecified_bool()
.
- Предоставить функцию члена
- Boost.SmartPtr operator_bool:
- Содержится в каталоге подробностей, поэтому он явно не предназначен для внешнего использования.
- Заголовочный файл предназначен для включения непосредственно в определение класса. См. shared_ptr.hpp для примера.
- Требуется включить
boost/detail/workaround.hpp
, прежде чем включатьsmart_ptr/detail/operator.hpp
. - Ожидается, что окружающий класс с поддержкой safe-bool будет:
- Укажите тип
this_type
. - Укажите тип
T
. - Предоставить переменную участника
T* px
.
- Укажите тип
- Boost.Spirit.Classic safe_bool
- Предназначен для внешнего использования.
- Использует шаблон CRTP.
- Предназначен для поддержки цепочки базового класса, позволяя использовать
boost::spirit::class::safe_bool
без указания множественного наследования в производном классе. - Ожидается, что класс с поддержкой safe-bool:
- Публично вытекает из
boost::spirit::classic::safe_bool< Derived >
. ЕслиDerived
уже наследуется отBase
, используйтеboost::spirit::classic::safe_bool< Derived, Base >
. - Предоставить функцию члена
bool operator_bool() const
.
- Публично вытекает из
В этом примере используется Boost 1.50. Каждый класс должен оценивать значение true в булевом контексте, если целое число, переданное конструктору, больше 0:
// Safe-bool idiom with Boost.Range.
#include <boost/range/detail/safe_bool.hpp>
class range_bool
{
public:
range_bool( int x ) : x_( x ) {}
private:
// None of these are required, but makes the implementation cleaner.
typedef boost::range_detail::safe_bool< int range_bool::* > safe_bool_t;
typedef safe_bool_t::unspecified_bool_type unspecified_bool_type;
int dummy;
public:
operator unspecified_bool_type() const
{
return safe_bool_t::to_unspecified_bool( x_ > 0, &range_bool::dummy );
}
private:
int x_;
};
// Safe-bool idiom with Boost.SmartPtr.
#include <boost/detail/workaround.hpp>
class smart_ptr_bool
{
public:
smart_ptr_bool( int x ) { px = ( x > 0 ) ? &dummy : 0 ; }
private:
typedef smart_ptr_bool this_type; // -.
typedef int T; // :- Required concepts when using
T* px; // -' smart_ptr operator_bool.
private:
T dummy; // Simple helper.
public:
#include <boost/smart_ptr/detail/operator_bool.hpp>
};
// Safe-bool idiom with Boost.Spirit.
#include <boost/spirit/include/classic_safe_bool.hpp>
class spirit_bool: public boost::spirit::classic::safe_bool< spirit_bool >
{
public:
spirit_bool( int x ) : x_( x ) {}
public:
// bool operator_bool() is required by the spirit safe_bool CRTP.
bool operator_bool() const { return x_ > 0; }
private:
int x_;
};
#include <iostream>
int main()
{
std::cout << "range_bool( -1 ): " << range_bool( -1 ) << std::endl
<< "range_bool( 1 ): " << range_bool( 1 ) << std::endl
<< "smart_ptr_bool( -1 ): " << smart_ptr_bool( -1 ) << std::endl
<< "smart_ptr_bool( 1 ): " << smart_ptr_bool( 1 ) << std::endl
<< "spirit_bool( -1 ): " << spirit_bool( -1 ) << std::endl
<< "spirit_bool( 1 ): " << spirit_bool( 1 ) << std::endl;
return 0;
}
Результат:
range_bool( -1 ): 0 range_bool( 1 ): 1 smart_ptr_bool( -1 ): 0 smart_ptr_bool( 1 ): 1 spirit_bool( -1 ): 0 spirit_bool( 1 ): 1
Я не знаю никаких альтернатив. Когда я столкнулся с идиомами safe-bool, большинство реализаций были вариантами копирования и вставки реализации, представленными в статье Bjorn Karlsson.