65.9K
CodeProject 正在变化。 阅读更多。
Home

boolean_cast

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.39/5 (13投票s)

2005年12月4日

2分钟阅读

viewsIcon

48591

downloadIcon

214

执行 bool、BOOL 和 VARIANT_BOOL 类型的值之间的转换。

动机

我们不能忽略编译器警告,但它们有时很烦人

void motivation(HWND hWnd)
{
  bool b = ::IsWindow(hWnd); // warning C4800
}

上面的代码会产生警告

warning C4800: 'BOOL' : forcing value to bool 'true' 
                       or 'false' (performance warning)

static_cast 会产生与上面给出的警告相同的警告。 然后你写

void wrong(HWND hWnd)
{
  bool b = (::IsWindow(hWnd) == TRUE);
}

行为是未定义的,因为 Win32 文档说

If the window handle identifies an existing window, 
                             the return value is nonzero.
If the window handle does not identify an existing window, 
                             the return value is zero.

您可能认为 BOOL 定义为 TRUEFALSE,但似乎是错误的。 然后你写

void right(HWND hWnd)
{
  bool b = (::IsWindow(hWnd) != 0);
}

您的工作已完成(您可以将 FALSE 写为 0)。 无论如何,您一定认为它仍然很烦人。 这就是 boolean_cast 的用武之地。

要求

boolean_cast

在命名空间 poost 中定义的 boolean_cast 安全地转换 boolBOOLVARIANT_BOOL 类型之间的值

void good(HWND hWnd)
{
  bool b = boolean_cast<bool>(::IsWindow(hWnd));
}

VARIANT_TRUE 定义为 ((short)-1),实际上,隐式转换是危险的

void good_save()
{
  VARIANT_BOOL vb = TRUE;
  ATLASSERT( vb != VARIANT_TRUE ); // wow!

  vb = boolean_cast<VARIANT_BOOL>(TRUE);
  ATLASSERT( vb == VARIANT_TRUE );
}

boolean_cast 提高了安全性和可读性。 但是,为什么要编写目标类型? 编译器必须知道类型。

auto_boolean

auto_boolean 使用已分配对象的类型作为目标类型

void best(HWND hWnd)
{
  bool b = auto_boolean(::IsWindow(hWnd));
}

这就是你想要的。 没有警告,没有烦恼。 请注意,auto_boolean 在像 VC6 或 eVC4 这样的损坏的编译器下不起作用。

工作原理

boolean_cast 的实现如下

template< class TargetT, class SourceT >
TargetT boolean_cast(SourceT b)
{
  typedef boolean_converter<TargetT, SourceT> converter_t;
  return converter_t::convert(b);
}

boolean_cast 将其任务委托给 boolean_converter 类模板。 真正的任务由模板执行。 让我们看一下实现

// primary template
template< class TargetT, class SourceT >
struct boolean_converter;

// full specialization
template< >
struct boolean_converter<bool, BOOL>
{
  static bool convert(BOOL b)
  {
    return b ? true : false;
  }
}

该任务被发送到“完全类模板特化”,具体取决于两种类型:TargetTSourceT

接下来,让我们看看 auto_boolean。 这有点技术性

template< class SourceT >
struct auto_boolean_type
{
  explicit auto_boolean_type(SourceT b) : m_b(b)
  { }

  // conversion operator
  template< class TargetT >
  operator TargetT() const
  { return boolean_cast<TargetT>(m_b); }

private:
  SourceT m_b;
};

template< class SourceT >
auto_boolean_type<SourceT> auto_boolean(SourceT b)
{
  return auto_boolean_type<SourceT>(b);
}

有趣的是,auto_boolean 返回的不是类型,而是 auto_boolean_type。 编译器必须将 auto_boolean_type 转换为目标类型。 他们找到并调用“转换运算符”,最后自动调用 boolean_cast,而不是你调用它。

关注点

reinterpret_caststatic_cast 在大多数程序中都得到大量使用。 如果您几个月没有查看您的代码,确定每个强制转换都在做什么可能很耗时,并且像 boolean_cast 这样的特定于域的强制转换可以帮助您减少此时间。

在以下情况下测试

参考文献

历史

  • 2005 年 12 月 5 日:上传了初始版本。
  • 2005 年 12 月 6 日:文档已更新。
© . All rights reserved.