【发布时间】:2026-01-03 18:50:01
【问题描述】:
是否有一个技巧可以让安全的 bool 习惯用法完全正常工作,而不必从执行实际实现的类派生?
对于“完全正常工作”,我的意思是类有一个运算符,允许它像一个布尔值一样被测试,但以一种安全的方式:
MyTestableClass a;
MyOtherTestableClass b;
//this has to work
if( a );
if( b );
//this must not compile
if( a == b );
if( a < b );
int i = a;
i += b;
例如使用此实现时
struct safe_bool_thing
{
int b;
};
typedef int safe_bool_thing::* bool_type;
safe_bool( const bool b ) { return b ? &safe_bool_thing::b : 0; }
class MyTestableClass
{
operator bool_type () const { return safe_bool( someCondition ); }
}
几乎没问题,除了 a == b 仍然可以编译,因为可以比较成员指针。与上面相同的实现,但是使用指向成员函数的指针而不是指向成员变量的指针有完全相同的问题。
可以完美运行的已知实现(例如,here 所述,或 boost 中使用的 safe_bool)要求可测试类派生自提供实际运算符实现的类。
我实际上认为没有办法绕过它,但并不完全确定。我尝试了一些看起来有点古怪的东西,但我认为它可能会起作用,但根本无法编译。为什么不允许编译器看到操作符返回一个safe_bool_thing,然后又可以转换为bool(),从而进行测试?
struct safe_bool_thing
{
explicit safe_bool_thing( const bool bVal ) : b( bVal ) {}
operator bool () const { return b; }
private:
const bool b;
safe_bool_thing& operator = ( const safe_bool_thing& );
bool operator == ( const safe_bool_thing& );
bool operator != ( const safe_bool_thing& );
};
class MyTestableClass
{
operator safe_bool_thing () const { return safe_bool_thing( someCondition ); }
};
MyTestableClass a;
if( a ); //conditional expression of type 'MyTestableClass' is illegal
【问题讨论】:
-
a == b 应该编译...对于两个布尔值非常有意义。你想要一个安全的布尔值还是绑定的、阻塞的和链式的布尔值? ;-)
-
对布尔值有意义,是的,但对两个完全不相关的类没有意义!
-
出于兴趣,如果您制作第一个版本,然后将
MyTestableClass::operator==设为私有会怎样?这有什么问题吗,不应该阻止a==b进行任何转换吗?在实践中,从safe_bool的助手继承通常是一件好的事情,所以我对所有标准实现都这样做并不感到惊讶。 -
取决于您的意思是哪个 operator== .. 如果您使用 operator == ( const MyTestableClass& ),它不会做任何偏离路线的事情。如果您使用 bool operator == ( const bool_type& ),那么它确实给出了我想要的行为。这样写有点奇怪,但它确实有效。也许您可以将其发布为答案?
-
我不认为有任何“当然”,我已经编辑了我的答案:-)