从@Xeo的优秀c++-faq问题中得知:C++11中safe bool习惯用法已过时吗?我了解到,因为在C++03中需要safe bool的上下文中将自动调用显式的用户定义转换为bool,所以不再需要safe bool习惯用法。
然而,重载运算符如&&、||和!似乎可以规避这一点。
需要operator!超出提供转换为bool的情况是罕见的,operator&&和operator||也是如此,但是C++表达式树实现(用于延迟执行和符号数学技术)确实需要覆盖这些内容。
当调用用户定义的运算符时,是否会发生“上下文转换”?需要什么样的SFINAE咒语才能确保operator&&或operator||的定义将正确地处理既实现“安全布尔”的类型又设计为“上下文转换”的类型?
为了澄清,给定:
以下内容在编译时被拒绝:
然而,重载运算符如&&、||和!似乎可以规避这一点。
需要operator!超出提供转换为bool的情况是罕见的,operator&&和operator||也是如此,但是C++表达式树实现(用于延迟执行和符号数学技术)确实需要覆盖这些内容。
当调用用户定义的运算符时,是否会发生“上下文转换”?需要什么样的SFINAE咒语才能确保operator&&或operator||的定义将正确地处理既实现“安全布尔”的类型又设计为“上下文转换”的类型?
为了澄清,给定:
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;
bool
转换将不会是一个候选项。 - Ben Voigtexplicit
是一个关键字,而不是一种范例。) - Luc Danton