【问题标题】:Safe bool idiom in boost?boost中的安全布尔成语?
【发布时间】:2012-07-31 16:01:26
【问题描述】:

boost 库是否提供了安全 bool 习惯用法的实现,以便我可以从中派生出我的类?

如果是 - 它在哪里?

如果不是 - 除了自己实施之外,我还有哪些选择?


我发现了以下类似的问题:“Is there a safe bool idiom helper in boost?”并且接受的答案建议在Boost.Operators 中使用bool_testable<>

不幸的是,当我检查boost manual 时,我在那里找不到它。使用它的代码也无法编译。

我还偶然发现了另一个 SO 问题“Was boost::bool_testable<> relocated or removed?”,那里的评论表明 bool_testable 实际上从未对任何版本的 boost 进行过发布。

关于这个主题还有一个有趣的article by Bjorn Karlsson,其中包含一个可以复制粘贴到我的项目中的代码。不过,我希望有一个普遍接受和维护的实用程序库(例如 boost)已经实现了它。


出于兼容性原因,我不想依赖 C++11。

【问题讨论】:

  • 您是否考虑过通过不隐式转换为bool来解决问题?
  • 本文第 3 页有一个可重复使用的 Safe Bool 实现:artima.com/cppsource/safebool.html
  • 谢谢。我没有提到它,但我确实看到了,我可能会复制粘贴该代码,但我希望一些普遍接受和维护的实用程序库(首先想到的是 Boost)已经这样做了。
  • 您可能对“stackoverflow.com/questions/10490675/…”的更新感兴趣

标签: c++ boost safe-bool-idiom


【解决方案1】:

我不知道提供安全布尔习语的普遍接受的实用程序库。在 Boost 中进行了一些尝试,它们经常引发关于如何提供安全布尔实现(命名约定、宏、内联包含、继承)的争论。因此,Boost 中至少存在三个实现,其中只有一个实现 Boost.Spirit.Classic's safe_bool 是为外部使用而设计的。


每个实现的细节和概念:

  • Boost.Range's safe_bool
    • 包含在 detail 目录中,因此未明确设计为供外部使用。
    • 使用模板助手类型和静态成员函数实现。
    • 启用安全布尔的类应:
      • 提供一个委托给静态safe_bool::to_unspecified_bool() 函数的operator boost::range_detail::safe_bool&lt; MemberPtr &gt;::unspecified_bool_type() const 成员函数。
  • Boost.SmartPtr's operator_bool:
    • 包含在 detail 目录中,因此未明确设计为供外部使用。
    • 头文件旨在直接包含在类定义中。有关示例,请参阅 shared_ptr.hpp
    • 需要在包含smart_ptr/detail/operator.hpp 之前包含boost/detail/workaround.hpp
    • 周围启用了安全布尔的类预计会:
      • 提供this_type 类型。
      • 提供T 类型。
      • 提供一个T* px 成员变量。
  • Boost.Spirit.Classic's safe_bool
    • 专为外部使用而设计。
    • 使用CRTP 模式。
    • 旨在支持基类链接,允许使用 boost::spirit::class::safe_bool 而无需对派生类强制进行多重继承。
    • 启用安全布尔的类应:
      • 公开派生自boost::spirit::classic::safe_bool&lt; Derived &gt;。如果Derived 已经继承自Base,则使用boost::spirit::classic::safe_bool&lt; Derived, Base &gt;
      • 提供bool operator_bool() const 成员函数。

此示例使用 Boost 1.50。如果传递给构造函数的整数大于 0,则每个类都应在布尔上下文中计算为 true:

// Safe-bool idiom with Boost.Range.
#include <boost/range/detail/safe_bool.hpp>
class range_bool
{
public:
  range_bool( int x ) : x_( x ) {}
private:
  // None of these are required, but makes the implementation cleaner.
  typedef boost::range_detail::safe_bool< int range_bool::* > safe_bool_t;
  typedef safe_bool_t::unspecified_bool_type unspecified_bool_type;
  int dummy;
public:
  operator unspecified_bool_type() const
  {
    return safe_bool_t::to_unspecified_bool( x_ > 0, &range_bool::dummy );
  }
private:
  int x_;
};

// Safe-bool idiom with Boost.SmartPtr.
#include <boost/detail/workaround.hpp>
class smart_ptr_bool
{
public:
  smart_ptr_bool( int x ) { px = ( x > 0 ) ? &dummy : 0 ; }
private:
  typedef smart_ptr_bool this_type; // -.
  typedef int T;                    //   :- Required concepts when using
  T* px;                            // -'   smart_ptr's operator_bool.
private:
  T dummy; // Simple helper.
public:
  #include <boost/smart_ptr/detail/operator_bool.hpp>
};

// Safe-bool idiom with Boost.Spirit.
#include <boost/spirit/include/classic_safe_bool.hpp>
class spirit_bool: public boost::spirit::classic::safe_bool< spirit_bool >
{
public:
  spirit_bool( int x ) : x_( x ) {} 
public:
  // bool operator_bool() is required by the spirit's safe_bool CRTP.
  bool operator_bool() const { return x_ > 0; }
private:
  int x_;
};

#include <iostream>

int main()
{
  std::cout << "range_bool( -1 ):     " << range_bool( -1 )     << std::endl
            << "range_bool(  1 ):     " << range_bool(  1 )     << std::endl
            << "smart_ptr_bool( -1 ): " << smart_ptr_bool( -1 ) << std::endl
            << "smart_ptr_bool(  1 ): " << smart_ptr_bool(  1 ) << std::endl
            << "spirit_bool( -1 ):    " << spirit_bool( -1 )    << std::endl
            << "spirit_bool(  1 ):    " << spirit_bool(  1 )    << std::endl;
  return 0;
}

结果输出:

范围布尔(-1):0
范围布尔(1):1
smart_ptr_bool(-1):0
smart_ptr_bool(1):1
精神布尔(-1):0
精神布尔(1):1

我不知道任何替代方案。当我遇到安全布尔习语时,大多数实现都是Bjorn Karlsson's article 中提供的实现的复制粘贴变体。

【讨论】:

    【解决方案2】:

    自 Boost 1.55 起,Boost.Core 中有 &lt;boost/core/explicit_operator_bool.hpp&gt; 标头。它要求您定义bool operator!() 并使用BOOST_EXPLICIT_OPERATOR_BOOL() 宏(也有它的变体BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL())。

    The documentation 有一个例子:

    template< typename T >
    class my_ptr
    {
        T* m_p;
    
    public:
        BOOST_EXPLICIT_OPERATOR_BOOL()
    
        bool operator!() const
        {
            return !m_p;
        }
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-16
      • 2011-09-08
      • 1970-01-01
      • 1970-01-01
      • 2011-04-25
      • 2018-04-23
      • 1970-01-01
      • 2011-09-12
      相关资源
      最近更新 更多