magic_enum icon indicating copy to clipboard operation
magic_enum copied to clipboard

enum_flags_name: return name for 0, if it exists

Open masbug opened this issue 1 year ago • 10 comments

Added constexpr that returns name for the value zero, if it exists.

masbug avatar Sep 04 '24 12:09 masbug

Since this changes behavior it should probably be opt in

ZXShady avatar Oct 04 '25 16:10 ZXShady

I don't think it should be opt in. It fixes a bug. If 0 isn't defined as an enum value then it will still work as before.

// this works same as before
enum E1 {
    A = 1<<0,
    B = 2<<1
}

vs.

// this will now resolve value 0 to "None"
enum E2 {
    None = 0,
    A = 1<<0,
    B = 2<<1
}```

masbug avatar Oct 09 '25 07:10 masbug

I don't think it should be opt in. It fixes a bug. If 0 isn't defined as an enum value then it will still work as before.

// this works same as before
enum E1 {
    A = 1<<0,
    B = 2<<1
}

vs.

// this will now resolve value 0 to "None"
enum E2 {
    None = 0,
    A = 1<<0,
    B = 2<<1
}```

I understand, but magic_enum::enum_values()[0] isn't 0 either, so this seems inconsistent to only apply it here, how about enum_cast<Bitflag>("None") ?

ZXShady avatar Oct 09 '25 07:10 ZXShady

It already works for both cases. See this test https://godbolt.org/z/nEKoP6j4n

#include <magic_enum/magic_enum.hpp>
#include <iostream>

enum class E1 : int {
    None = 0,
    Flag1 = 1 << 0,
    Flag2 = 2 << 1
};

int main() {
    static_assert(magic_enum::enum_values<E1>()[0] == E1::None);
    static_assert(magic_enum::enum_cast<E1>("None") == E1::None);

    return 0;
}

masbug avatar Oct 09 '25 08:10 masbug

@masbug

This is not a bitflag, you must do this

template <>
struct magic_enum::customize::enum_range<E1> {
  static constexpr bool is_flags = true;
};

// now your code fails

otherwise you will be reflecting from [-128,127] instead of N^2

@Neargye

It seems alot of people forget to set this boolean to true themselves, shouls it auto deduce?

ZXShady avatar Oct 09 '25 08:10 ZXShady

@ZXShady Thanks for pointing that out. I see now what you mean. I suppose this is the correct behavior for flags, since 0 is a special state.

static_assert(magic_enum::enum_values<E1>()[0] == E1::Flag1);

But this is missing:

static_assert(magic_enum::enum_cast<E1>("None") == E1::None);

masbug avatar Oct 09 '25 09:10 masbug

There was some discussion about it including the 0 value.

#314

ZXShady avatar Oct 10 '25 08:10 ZXShady

@ZXShady

It seems alot of people forget to set this boolean to true themselves, shouls it auto deduce?

It would be great, but I haven't found a reliable way to detect that these are flags yet.

Personally, I don't think zero should be included by default. I would prefer two separate options: flags and flags_with_zero (or flags_and_zero), though this is open for discussion.

Neargye avatar Nov 21 '25 15:11 Neargye

@ZXShady It would be great, but I haven't found a reliable way to detect that these are flags yet.

I do it myself by checking for & and | operators if they are overloaded.

ZXShady avatar Nov 21 '25 22:11 ZXShady

Could try adding auto detection. Then we definitely need swith using namespace magic_enum::bitwise_operators to enable_bitwise_operators = true 😁

Neargye avatar Nov 22 '25 16:11 Neargye