我见过的提升实现了一个漂亮的帽子戏法,他们以某种方式使用()运算符重载的类boost ::系统:: ERROR_CODE的实例计算为一个布尔值
class error_code
{
...
typedef void (*unspecified_bool_type)();
static void unspecified_bool_true() {}
operator unspecified_bool_type() const // true if error
{
return m_val == 0 ? 0 : unspecified_bool_true;
}
...
}
Run Code Online (Sandbox Code Playgroud)
这导致可以检查这样的错误
...
boost::system::error_code err
some_boost_func(err);
if(err)
{
//handle error
}
....
Run Code Online (Sandbox Code Playgroud)
所以我一直在问自己..那里发生了什么?这似乎在某种程度上与函数指针的使用有关......如果我调用会发生什么,这会err评估函数本身还是函数指针?但是void (*unspecified_bool_type)();函数如何返回一个值
return m_val == 0 ? 0 : unspecified_bool_true;
Run Code Online (Sandbox Code Playgroud)
AnT*_*AnT 15
它确实与函数指针的核心功能相关很少(或没有).这是一个技巧,允许人们为类编写一个"安全"类似布尔的转换.
当人们希望某个类在if(并且通常在逻辑上下文中)可用时,通常可以将其转换为bool.如在
class Error {
public:
operator bool() const { /* whatever */ }
};
Run Code Online (Sandbox Code Playgroud)
现在你可以做到
Error err;
...
if (err) // automatically intepreted as `if (err.operator bool())`
...
Run Code Online (Sandbox Code Playgroud)
但是,由于bool类型是C++中的一个整体类型,当有人意外地写出类似的内容时,这可能会导致不良后果
int i = err;
Run Code Online (Sandbox Code Playgroud)
或者err在算术表达式中使用并且它静静地编译.
出于这个原因,在许多情况下,人们更喜欢将转换引入指针类型,而不是转换为bool,如
class Error {
public:
operator void *() const {
// Return null pointer for `false` and any non-null pointer for `true`
}
};
Run Code Online (Sandbox Code Playgroud)
这是更好的,因为可以使用它if,但一个人不能犯下以前的错误int.即
if (err) // automatically interpreted as `if (err.operator void *() != 0)`
...
Run Code Online (Sandbox Code Playgroud)
将编译并按预期工作,因为编译器会自动将err对象转换为指针类型.
但是,这种转换也会自动应用于指针上下文中(除了布尔上下文之外),这意味着仍然会意外地执行
void *p = err;
Run Code Online (Sandbox Code Playgroud)
要么
free(err);
Run Code Online (Sandbox Code Playgroud)
它会安静地编译.这也是不可取的.
为了使意外滥用此类错误类更加困难,最好使用一些更具"异国情调"的指针类型,如指向函数的指针.这正是您在引用的代码中看到的内容.将unspecified_bool_type被用作基于指针的伪的布尔类型.返回空值,并返回false指向虚unspecified_bool_true函数的指针true.该函数unspecified_bool_true永远不会被调用,也不会被调用.它仅用于保留一些唯一的指针值以用作true返回.
在某些情况下,人们更进一步,使用更"异国情调"的指针类型:指向类成员类型的指针.但是对于大多数应用程序来说,指向函