I have class like this:
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 ;
}
the idea of constexpr static members is to avoid double typing, e.g.
if (insert() == InsertResult::INSERTED){
// OK...
}
vs
if (insert() == InsertResult::Status::INSERTED){
// OK...
}
Any easy way to make it "better" without using C enum
?
In C++20 you would do using enum Status;
.
Pre-C++20 the best idea I have is writing a macro to generate your constexpr variables for you. The example below uses macro_sequence_for
, a little library I made to simplify preprocessor loops.
#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;
Then this:
MAKE_ENUM( E,
(e1)
(e2)
(e3)
)
Expands to this:
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;
And here's a longer version that lets you specify the enum constant values:
#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)
)