C ++安全bool包装器

时间:2017-01-16 20:40:55

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

我正在尝试使用 safe bool idiom 设计 bool包装结构。
解决这个问题的经典实现非常简单:骨架可能是这样的:

struct Bool final
{
  Bool() = default;

  Bool(bool value)
    : _value{value}
  {}

  explicit operator bool() const {
    return _value;
  }

private:
  bool _value{false};
};

我正在努力改进的部分是如何构建Bool 例如,我想避免设计隐含的缩小:

Bool b1(45); // yields warnings, but it compiles
Bool b2{3};  // not ok by standard

我试图用模板伤害自己,但没有成功。

我怎么能让它发挥作用?

4 个答案:

答案 0 :(得分:56)

您可以通过显式删除所有其他构造函数来实现此目的。

struct Bool final
{
    template<class T>
    Bool(T) = delete;

    Bool(bool value);
};

答案 1 :(得分:23)

添加并显式删除模板构造函数:

template <typename T>
Bool(T) = delete;

它比其他构造函数更好地匹配实际bool之外的任何内容,因此会阻止隐式转换。

答案 2 :(得分:18)

如果您需要:
一个只有“true”或“false”且不能隐式转换为int / char / pointer的变量然后我会看一下使用枚举类:

enum class Bool {
    False,
    True,
};

答案 3 :(得分:13)

  

我试图设计一个应用安全bool习语的bool包装器结构。

唐&#39;吨

安全bool成语仅在C ++ 03及更早版本中有用 - 如果你表达你的类型是&#34; truthy&#34;做类似的事情:

struct A {
    operator bool() const;
};

你遇到各种各样的问题,如:

A{} + 4;    // ok?!
A{} < 0;    // ok?!
A{} == B{}; // ok if B also has operator bool??!

因此,使用函数指针(当然,函数指针!)来解决这个意外隐式转换问题的安全bool习惯用法。

在C ++ 11中,我们有一个更好的解决方案:

struct A {
    explicit operator bool() const;
};

完全我们想要什么。事实上,解决这个问题是literally designed。虽然安全的bool成语是相当复杂的脚手架,explicit operator bool使用起来非常简单,只做正确的事。你不需要一个包装器 - 使用你的包装器比直接写explicit operator bool更难。

此外,您的包装器对用户施加了(a)不可导出性,因为您使Bool成为最终成员,而(b)成为额外的bool成员,您必须保持同步,因此它引入而不是解决问题。考虑一下你需要做多少工作:

template <class T>
struct my_unique_ptr : Bool { ... };

VS

template <class T>
struct my_unique_ptr {
    T* ptr;

    explicit operator bool() const { return ptr; }
};