C++ operator() 重载 boost::system::error_code 技巧

标签 c++ boost

我看到了 boost 实现的一个绝妙技巧,他们以某种方式使用 () 运算符的重载来将类 boost::system::error_code 的实例评估为 bool 值

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;
}
...
}

这导致有可能检查这样的错误

...
boost::system::error_code err

some_boost_func(err);
if(err)
{
    //handle error
}
....

所以我一直在问自己.. 那里发生了什么? 这似乎在某种程度上与函数指针的使用有关...... 如果我调用 err 会发生什么?这是评估函数本身还是函数指针? 但是 void (*unspecified_bool_type)(); 函数如何返回

中的值
return m_val == 0 ? 0 : unspecified_bool_true;

最佳答案

它确实与函数 指针的核心功能特别无关(或根本没有)。这是一种允许为类编写“安全的”类 bool 转换的技巧。

当希望某个类在 if 下(通常在逻辑上下文中)可用时,通常会将其转换为 bool。如

class Error {
public:
  operator bool() const { /* whatever */ }
};

现在你可以做

Error err;
...
if (err) // automatically intepreted as `if (err.operator bool())`
  ...

但是,由于 bool 类型在 C++ 中是一个整数类型,这可能会导致不良后果,当有人不小心写下类似的东西时

int i = err;

或者在算术表达式中使用 err 并安静地编译。

出于这个原因,在许多情况下,人们更愿意引入到指针类型的转换,而不是转换为bool,如

class Error {
public:
  operator void *() const { 
    // Return null pointer for `false` and any non-null pointer for `true`
  }
};

这样更好,因为可以在 if 下使用它,但不能用 int 犯之前的错误。 IE。

 if (err) // automatically interpreted as `if (err.operator void *() != 0)`
   ...

将按预期编译和工作,因为编译器会自动将 err 对象转换为指针类型。

但是,这种转换也会自动应用于指针上下文(除了 bool 上下文),这意味着仍然可以不小心做

void *p = err;

free(err);

它会安静地编译。这也是不可取的。

为了更难意外误用此类错误类,使用一些更“奇特”的指针类型是个好主意,比如指向函数的指针。这正是您在引用的代码中看到的。 unspecified_bool_type 用作基于指针的伪 bool 类型。 false 返回 Null 值,true 返回指向虚拟 unspecified_bool_true 函数的指针。函数 unspecified_bool_true 从未被调用,也从未打算被调用。它的存在只是为了保留一些唯一的指针值以用作 true 返回值。

在某些情况下,人们更进一步,使用一种更加“奇特”的指针类型:指向类成员的指针类型。但是对于大多数应用程序来说,指向函数的指针已经足够“奇特”了。

关于C++ operator() 重载 boost::system::error_code 技巧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11426853/

相关文章:

c++ - 用户友好的 CMake 库路径 (CCMake)

c++ - 我怎样才能简单地使用无法识别的字符?

c++ - 反复读写交替

c++ - 使用 libtool 从共享库加载重复的函数名

c++ - 如何在 Qt 中将 QVariant 转换为 QString,反之亦然?

c++ - 如何迭代boost graph以获取顶点的传入和传出边缘?

c++ - boost::unsafe_any_cast 为空时无效的非空指针?

c++ - XCode 9.3 升级或替换 libc++

c++ - 如何将单元测试与 assert() 相结合

c++ - 为 ubuntu 和 libboost_date_time boost 1.49