C++ 安全布尔包装器
C++ safe bool wrapper
我正在尝试设计一个应用 safe bool idiom.
的 bool wrapper 结构
解决这个问题的经典实现非常简单:骨架可能是这样的:
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
我试图用模板伤害自己,但没有成功。
我怎样才能让它发挥作用?
您可以通过显式删除所有其他构造函数来实现此目的。
struct Bool final
{
template<class T>
Bool(T) = delete;
Bool(bool value);
};
添加和显式删除模板构造函数:
template <typename T>
Bool(T) = delete;
它与实际 bool
以外的任何其他构造函数相匹配,因此可以防止隐式转换。
如果你刚好需要:
一个只有 "true" 或 "false" 并且不能隐式转换为 int/char/pointer 的变量然后我会考虑使用枚举 class:
enum class Bool {
False,
True,
};
I'm trying to design a bool wrapper struct applying the safe bool idiom.
不要。
safe bool 惯用语仅在 C++03 及更早版本中相关 - 如果您通过执行以下操作来表达您的类型是 "truthy":
struct A {
operator bool() const;
};
你会 运行 遇到各种问题,例如:
A{} + 4; // ok?!
A{} < 0; // ok?!
A{} == B{}; // ok if B also has operator bool??!
所以 safe bool 习语是解决这个意外隐式转换问题的方法,它使用函数指针(当然是函数指针!)。
在 C++11 中,我们有一个更好的解决方案:
struct A {
explicit operator bool() const;
};
完全我们想要的。其实就是literally designed来解决这个问题。虽然 safe bool 习语是相当复杂的脚手架,但 explicit operator bool
使用起来超级简单,而且做正确的事。您不需要包装器 - 使用包装器实际上比直接编写 explicit operator bool
更难。
此外,您的包装器强加给用户 (a) non-derivability 因为您将 Bool
设为最终版本和 (b) 一个额外的 bool
成员,您必须保持同步,所以它引入而不是解决问题。考虑一下您需要执行多少工作:
template <class T>
struct my_unique_ptr : Bool { ... };
对
template <class T>
struct my_unique_ptr {
T* ptr;
explicit operator bool() const { return ptr; }
};
我正在尝试设计一个应用 safe bool idiom.
的 bool wrapper 结构
解决这个问题的经典实现非常简单:骨架可能是这样的:
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
我试图用模板伤害自己,但没有成功。
我怎样才能让它发挥作用?
您可以通过显式删除所有其他构造函数来实现此目的。
struct Bool final
{
template<class T>
Bool(T) = delete;
Bool(bool value);
};
添加和显式删除模板构造函数:
template <typename T>
Bool(T) = delete;
它与实际 bool
以外的任何其他构造函数相匹配,因此可以防止隐式转换。
如果你刚好需要:
一个只有 "true" 或 "false" 并且不能隐式转换为 int/char/pointer 的变量然后我会考虑使用枚举 class:
enum class Bool {
False,
True,
};
I'm trying to design a bool wrapper struct applying the safe bool idiom.
不要。
safe bool 惯用语仅在 C++03 及更早版本中相关 - 如果您通过执行以下操作来表达您的类型是 "truthy":
struct A {
operator bool() const;
};
你会 运行 遇到各种问题,例如:
A{} + 4; // ok?!
A{} < 0; // ok?!
A{} == B{}; // ok if B also has operator bool??!
所以 safe bool 习语是解决这个意外隐式转换问题的方法,它使用函数指针(当然是函数指针!)。
在 C++11 中,我们有一个更好的解决方案:
struct A {
explicit operator bool() const;
};
完全我们想要的。其实就是literally designed来解决这个问题。虽然 safe bool 习语是相当复杂的脚手架,但 explicit operator bool
使用起来超级简单,而且做正确的事。您不需要包装器 - 使用包装器实际上比直接编写 explicit operator bool
更难。
此外,您的包装器强加给用户 (a) non-derivability 因为您将 Bool
设为最终版本和 (b) 一个额外的 bool
成员,您必须保持同步,所以它引入而不是解决问题。考虑一下您需要执行多少工作:
template <class T>
struct my_unique_ptr : Bool { ... };
对
template <class T>
struct my_unique_ptr {
T* ptr;
explicit operator bool() const { return ptr; }
};