我有一个Flags
类,其行为类似于std::bitset
,它正在替换旧代码库中的bitpacked整数。为了强制遵守较新的类,我想禁止从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
,同时禁止其他值?
答案 0 :(得分:6)
一种方法:
添加一个带void*
。
由于文字0
可隐式转换为void*
空指针,而文字1
不是,因此这将指示所需的行为。为安全起见,您可以断言指针在ctor中为空。
缺点是现在你的类可以从任何可隐式转换为void *
的东西构建。一些意想不到的事情是如此可转换 - 例如在C ++ 11之前,std::stringstream
可以转换为void*
,基本上是一个黑客,因为explicit operator bool
尚不存在。
但是,只要你意识到潜在的陷阱,这在你的项目中可能会很好。
编辑:
实际上,我记得一种让这更安全的方法。而不是void*
使用指向私有类型的指针。
可能看起来像这样:
class Flags {
private:
struct dummy {};
public:
Flags (dummy* d) { ... }
...
};
文字0
转换仍然有效,而且某些用户定义的类型无意中意外转换为Flags::dummy *
会更加困难。