От превосходного c++-faq
вопроса @ Xeo: Является ли идиома safe-bool устаревшей в C ++ 11? Я узнал, что идиома safe bool больше не нужна, потому что explicit
user- определенное преобразование в bool
будет автоматически вызываться в тех случаях, когда в C ++ 03 требовался безопасный bool.
Однако возможность перегрузки таких операторов, как &&
, ||
и !
, кажется, обходит это.
Случаи, когда operator!
необходим помимо обеспечения преобразования в bool
, являются редкими, как и operator&&
и operator||
, но реализации дерева выражений C ++ (используемые для методов отложенного выполнения и символьной математики) требуют переопределения это.
Происходит ли "контекстное преобразование", когда вызывается пользовательский оператор? Какой тип заклинания SFINAE необходим, чтобы убедиться, что определение operator&&
или operator||
будет работать правильно как с типами, реализующими «безопасный bool», так и с типами, предназначенными для «контекстного преобразования»?
Для уточнения дано:
class uses_safe_bool
{
void f() {};
typedef void (uses_safe_bool::* safe_bool)();
public:
operator safe_bool() const { return (rand() & 1)? &uses_safe_bool::f: 0; }
};
class uses_explicit_bool
{
public:
explicit operator bool() const { return rand() & 1; }
};
template<typename T>
class deferred_expression
{
// Not convertible to bool
public:
T evaluate() const;
};
Какие подписи требуются для operator||
, так что все следующие выражения являются действительными:
deferred_expression<bool> db;
uses_safe_bool sb;
uses_explicit_bool eb;
int i;
auto test1 = sb || db;
auto test2 = eb || db;
auto test3 = true || db;
auto test4 = false || db;
auto test5 = i || db;
они используют другую перегрузку:
auto test6 = db || db;
deferred_expression<int> di;
auto test7 = di || db;
и следующие отклоняются во время компиляции:
std::string s;
auto test7 = s || db;
std::vector<int> v;
auto test8 = v || db;
deferred_expression<std::string> ds;
auto test9 = ds || db;