DRY: C++11枚举类 vs C枚举

3
我有这样的课程:
struct InsertResult{
    enum class Status{
        INSERTED            ,
        UPDATED_IN_PLACE    ,
        REPLACED            ,
        SKIP_INSERTED       ,
        ERROR_NO_MEMORY     ,
        ERROR_INVALID       ,
        ERROR
    };

    bool        ok;
    Status      status;
    // more members here...

    // spill the enum:
    constexpr static auto INSERTED          =  Status::INSERTED         ;
    constexpr static auto UPDATED_IN_PLACE  =  Status::UPDATED_IN_PLACE ;
    constexpr static auto REPLACED          =  Status::REPLACED         ;
    constexpr static auto SKIP_INSERTED     =  Status::SKIP_INSERTED    ;
    constexpr static auto ERROR_NO_MEMORY   =  Status::ERROR_NO_MEMORY  ;
    constexpr static auto ERROR_INVALID     =  Status::ERROR_INVALID    ;
    constexpr static auto ERROR             =  Status::ERROR            ;
}

constexpr静态成员的概念是为了避免重复输入,例如。
if (insert() == InsertResult::INSERTED){
//  OK...
}

vs
if (insert() == InsertResult::Status::INSERTED){
//  OK...
}

有没有一种简单的方法可以使它“更好”,而不使用 C 枚举?

4
换句话说,您希望在不引入新的范围的情况下加强类型检查? - undefined
1
枚举在C++中与C一样重要。为什么你要避免(特别是)"C枚举"呢? - undefined
10
在C++20中,可以很好地解决这个问题,只需使用using enum Status;即可。 - undefined
@Artyer 直到 C++20?不可能吧? - undefined
这取决于你对“容易”的理解——如果你想在一个地方定义所有成员,而不必在常量中重复代码,那么可以通过使用X-macro来实现。然而,结果可能是一个不太容易阅读的枚举定义。如果你有很多成员和很多变化,尽管可能需要付出一些努力,但这可能是值得的——我真的是指很多... - undefined
1个回答

5
在C++20中,你可以使用using enum Status;来实现。
在C++20之前,我最好的建议是编写一个宏来为你生成constexpr变量。下面的示例使用了macro_sequence_for,这是我制作的一个简化预处理器循环的小库。

在gcc.godbolt.org上运行

#include <macro_sequence_for.h>

#define MAKE_ENUM(name_, members_) \
    enum class name_ {SF_FOR_EACH(BODY_ENUM_ELEM, SF_NULL, SF_NULL,, members_)};\
    SF_FOR_EACH(BODY_VAR, SF_STATE, SF_NULL, name_, members_)

#define BODY_ENUM_ELEM(n, d, x) x,
#define BODY_VAR(n, d, x) [[maybe_unused]] static constexpr d x = d::x;

然后这个:
MAKE_ENUM( E,
    (e1)
    (e2)
    (e3)
)

扩展为:

enum class E
{
    e1,
    e2,
    e3,
};

[[maybe_unused]] static constexpr E e1 = E::e1;
[[maybe_unused]] static constexpr E e2 = E::e2;
[[maybe_unused]] static constexpr E e3 = E::e3;

这是一个更长的版本,可以让您指定枚举常量的值。
#include <macro_sequence_for.h>

#define MAKE_ENUM(name_, members_) \
    enum class name_ {SF_FOR_EACH(BODY_ENUM_ELEM, SF_NULL, SF_NULL,, members_)};\
    SF_FOR_EACH(BODY_VAR, SF_STATE, SF_NULL, name_, members_)

#define BODY_ENUM_ELEM(n, d, ...) BODY_ENUM_ELEM_SELECT(__VA_ARGS__, BODY_ENUM_ELEM_A, BODY_ENUM_ELEM_B,)(__VA_ARGS__)
#define BODY_ENUM_ELEM_SELECT(x, y, z, ...) z
#define BODY_ENUM_ELEM_A(name_, init_) name_ = init_,
#define BODY_ENUM_ELEM_B(name_) name_,

#define BODY_VAR(n, d, ...) BODY_VAR_(n, d, __VA_ARGS__,)
#define BODY_VAR_(n, d, x, ...) [[maybe_unused]] static constexpr d x = d::x;

MAKE_ENUM( E,
    (e1)
    (e2, 42)
    (e3)
)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接