3

So far I have:

#include <cstdint>

enum class le_enum : uint32_t {
    FLAG_0 = 0x00000000,
    FLAG_1 = 0x00000001,
    FLAG_2 = 0x00000002,
    FLAG_3 = 0x00000004,
    FLAG_4 = 0x00000008,
    FLAG_5 = 0x00000010,
    FLAG_6 = 0x00000020,
    FLAG_7 = 0x00000040
};

inline uint32_t operator|(const le_enum lhs, const le_enum rhs) {
    return (uint32_t)lhs | (uint32_t)rhs;
}

inline uint32_t operator|(const uint32_t lhs, const le_enum rhs) {
    return lhs | (uint32_t)rhs;
}

int main(int argc, char** argv) {

    uint32_t flags = le_enum::FLAG_0 | le_enum::FLAG_7;
    uint32_t flags2 = le_enum::FLAG_2 | le_enum::FLAG_3 | le_enum::FLAG_5;

    return 0;
}

where I need to define 2 operators.

Can I enable this with with less code?

PinkTurtle
  • 6,942
  • 3
  • 25
  • 44
  • 4
    That seems like a reasonable amount of code. Though given that you're treating these as `uint32_t` at the first chance you get, I'd recommend forgoing the `enum class` altogether and just using good old-fashioned C-style `enum`. Then the `operator|` is free. – Silvio Mayolo Apr 19 '22 at 01:37
  • 4
    Don’t return it as a uint32_t – Taekahn Apr 19 '22 at 01:37
  • I made a mistake in the mvce, it's corrected. – PinkTurtle Apr 19 '22 at 01:38
  • @Taekahn good point. That would save an operator. But.. it's semantically incorrect then. – PinkTurtle Apr 19 '22 at 01:40
  • 2
    @PinkTurtle: "*But.. it's semantically incorrect then.*" But you're the one who wants to use an enum class as a bitfield. So by the semantics you've already established, it's OK. – Nicol Bolas Apr 19 '22 at 02:00
  • All i'm saying is that the result of a bitwise-op here doesn't result in a valid `le_enum` flag. If I wanna parse the result of said op, I will parse a uint32_t, not a le_enum - which seems correct to me. – PinkTurtle Apr 19 '22 at 02:04
  • You don't need a defined name in `le_enum` to make it a valid value. Any value that's in the range of `uint32_t` will be valid in your case. – Ranoiaetep Apr 19 '22 at 02:09
  • @Ranoiaetep `0x00000021` is not defined in the enum so as far as i'm concerned it's not a valid flag ;) (it's a combination of flag**s**). – PinkTurtle Apr 19 '22 at 02:10
  • @PinkTurtle If you want it to always be converted to a `uint`, then why not just use the C-style `enum` as ***Silvo*** suggested – Ranoiaetep Apr 19 '22 at 02:14
  • I guess I could, but then I can't use a named type in some functions argument - the named enum gives better readability imo. – PinkTurtle Apr 19 '22 at 02:16
  • @PinkTurtle You can still use the named type in function argument: https://godbolt.org/z/sfsbzd1Wj – Ranoiaetep Apr 19 '22 at 02:21
  • @Ranoiaetep I misspoke what I had in mind - I thought of wrapping an anonymous enum in a (e.g.) `le_enum` namespace so I don't expose enum flags outside of that namspace, but then the enum is well... anonymous so it won't work either way. I'll stick to my mcve. – PinkTurtle Apr 19 '22 at 02:37
  • 1
    @PinkTurtle Maybe you want to do this: https://godbolt.org/z/PMP9v6qoM – Ranoiaetep Apr 19 '22 at 02:49
  • see [`std::byte` implementation](https://en.cppreference.com/w/cpp/types/byte) which is almost the same as yours: allowing bitwise operations but not arithmetic ones. In Windows you just need [`DEFINE_ENUM_FLAG_OPERATORS(le_enum)`](https://stackoverflow.com/a/19592298/995714) – phuclv Apr 19 '22 at 04:45
  • 1
    @PinkTurtle -- `0x00000021 ` is a valid value for that enumerated type. – Pete Becker Apr 19 '22 at 13:38

0 Answers0