更确切地说,我想要的功能是将枚举隐式地转换为它的子集枚举,反之亦然。
我希望它工作的代码:
enum class Human {
A = 1,
B = 2,
};
enum class Male { // subset of Human
A = Human::A,
};
enum class Female { // subset of Human
B = Human::B,
};
// some functions can handle all humans
void human_func(Human h) {
// ...
}
// some only take a subset of humans
void male_func(Male m) {
// ...
}
void female_func(Female m) {
// ...
}
// and user only uses values of Human as token
constexpr auto SOMEONE = Human::A;
int main() {
human_func(SOMEONE); // ok
male_func(SOMEONE); // also ok, Human::A implicitly converted to Male
female_func(SOMEONE); // failed, can't convert Human::A to Female.
}
但是enum不能进行转换。现在我有两个选择:
// 1. static_assert with template parameter
template <Human H>
void female_func() {
static_assert(H == Human::B);
// ...
}
// 2. manually convert it
#define _ENUM_TO_ENUM(e1, e2) \
static_cast<e2>(static_cast<std::underlying_type_t<decltype(e1)>>(e1))
void female_func(_ENUM_TO_ENUM(SOMEONE, Female)) {
// But this way the compiler does not check if the value is valid.
// I can put anything in.
// ...
}
那么,还有其他的技术可以做到这一点吗?
2条答案
按热度按时间ubbxdtey1#
我认为这是继承和多态的典型用例。
如果您考虑将
Man
和Woman
枚举改为类,两者都为多态Human
类派生,并且只保留性别的枚举,那么您“希望工作”的代码肯定会工作。以下是所需返工的示例:
现在你可以像下面这样写你的函数:
并按以下方式使用它们:
它工作的原因是,对于继承,
Man
是Human
。Woman
也是如此。u3r8eeie2#
C++
中的enum class
不能与另一个enum class
有任何类型的is a
关系,至少在语言级别上是这样。您可以使用标准类型层次结构来实现您想要的功能,例如
Male
is a
Human
和Female
is a
Human
,如示例代码所示。虽然,这可能是你正在寻找的相反。示例代码