我有一个 Flags
类,它的行为类似于 std::bitset
,它正在替换旧代码库中的位打包整数。为了强制遵守较新的类,我想禁止从 int
类型进行隐式转换。
enum class Flag : unsigned int {
none = 0,
A = 1,
B = 2,
C = 4,
//...
};
class Flags {
public:
Flags();
Flags(const Flag& f);
explicit Flags(unsigned int); // don't allow implicit
Flags(const Flags&);
private:
unsigned int value;
};
我想只允许来自 Flag
和 Flags
类型的隐式构造和赋值。但是,我仍然希望一些函数调用采用 Flags
参数来接受文字 0
,但不接受其他整数:
void foo(const Flags& f);
foo(Flags(0)); // ok but ugly
foo(1); // illegal because of explicit constructor
foo(0); // illegal, but I want to allow this
这可能吗?允许隐式转换 0
而不允许其他值?
最佳答案
一种方法:
添加一个接受 void*
的构造函数。
由于文字 0
可以隐式转换为 void*
空指针,而文字 1
则不能,这将提供所需的行为表明的。为了安全起见,您可以断言构造函数中的指针为空。
缺点是现在您的类可以从任何可隐式转换为 void *
的内容构造。一些意想不到的东西是可以转换的——例如在 C++11 之前,std::stringstream
可以转换为 void*
,基本上是 hack 因为 explicit operator bool
还不存在。
但是,只要您意识到潜在的陷阱,这在您的项目中可能会奏效。
编辑:
其实,我想起了一个让这更安全的方法。使用指向私有(private)类型的指针代替 void*
。
它可能看起来像这样:
class Flags {
private:
struct dummy {};
public:
Flags (dummy* d) { ... }
...
};
文字 0
转换仍然有效,并且某些用户定义的类型无意中意外转换为 Flags::dummy *
的难度要大得多。
关于c++ - 允许对单个值进行隐式转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44511003/