提问人:ke_bitter 提问时间:6/2/2023 最后编辑:digito_evoke_bitter 更新时间:6/3/2023 访问量:106
如何在 C++ 中将枚举隐式转换为其子集,反之亦然?
How can I implicitly convert an enum to its subset and vice versa in C++?
问:
更准确地说,我想要的功能就像将枚举隐式转换为其子集枚举,反之亦然。
我希望它工作的代码:
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.
}
但是枚举不能进行转换。现在我有两个选择:
// 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赞
Fareanor
6/2/2023
#1
我认为这是继承和多态性的典型用例。
如果您考虑将 和 枚举改为类,既派生多态类,又只保留性别的枚举,那么您“希望工作”的代码肯定会起作用。Man
Woman
Human
以下是所需返工的示例:
enum class Gender {MALE, FEMALE};
struct Human
{
Gender m_gender;
Human(Gender g) : m_gender{g}
{}
virtual ~Human() = default;
};
struct Man : public Human
{
Man() : Human{Gender::MALE}
{}
};
struct Woman : public Human
{
Woman() : Human(Gender::FEMALE)
{}
};
现在,您可以按如下方式编写函数:
void human_func(const Human & h)
{
//...
}
void man_func(const Man & m)
{
//...
}
void woman_func(const Woman & w)
{
//...
}
并按以下方式使用它们:
int main()
{
Man man;
human_func(man); // OK --> Human
man_func(man); // OK --> Man
//woman_func(man); NOK (invalid: a Man is not a Woman)
return 0;
}
它之所以有效,是因为对于继承,a 是 ..Man
Human
Woman
1赞
RandomBits
6/2/2023
#2
至少在语言层面上,一个 in 不能与另一个 in 有任何类型的关系。enum class
C++
is a
enum class
您可以使用标准类型层次结构实现所需的内容,如示例代码所示。虽然,这可能与您正在寻找的相反。Male
is a
Human
Female
is a
Human
示例代码
#include <iostream>
using std::cin, std::cout, std::endl;
struct Human {
};
struct Male : public Human {
};
struct Female : public Human {
};
// 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
int main() {
auto human = Human{};
human_func(human);
// male_func(human); This would not compile
// female_func(human); This would not compile
auto male = Male{};
human_func(male);
male_func(male);
// female_func(male); This would not compile
auto female = Female{};
human_func(female);
// male_func(female); This would not compile
female_func(female);
}
评论
explicit
female_func