magic_enum icon indicating copy to clipboard operation
magic_enum copied to clipboard

constexpr enum map

Open schaumb opened this issue 2 years ago • 11 comments

The C++17 standard does not allow to use allocators, and dynamic containers (like std::unordered_map, std::map) in constexpr time. It is a handy feature, if magic_enum would offer an enum_map<EnumType, T>, which is implemented as std::array<T, enum_count<EnumType>> or std::array<optional<T>, enum_count<EnumType>> with a typesafe O(1) complexity operator[](EnumType), at(EnumType) functions , and stl-like constexpr interface.

schaumb avatar Mar 02 '22 14:03 schaumb

Consider EnumMap/EnumSet from https://github.com/teslamotors/fixed-containers Uses magic_enum under the hood and is fully constexpr.

alexkaratarakis avatar Mar 04 '22 00:03 alexkaratarakis

Thanks @alexkaratarakis , but I have only C++17 std available compiler, fixed-containers use C++20

schaumb avatar Mar 04 '22 08:03 schaumb

I think these containers not fits to the magic_enum.hpp header file.

Probably it need to put to an another header file, like magic_enum_containers.hpp.

But then the library looses the "only one header" property. What do you think @Neargye ?

schaumb avatar Mar 11 '22 15:03 schaumb

Are we missing something the current api? Do we need containers?

struct enum_map<EnumType, T> {
optional<T> values[enum_cout<EnumType>()];
auto operator[](E v)
  if (const auto index = enum_index<EnumType>(v); index.has_value()) {
    return values[*index];
  }
  return nullopt;
}

Neargye avatar Mar 11 '22 16:03 Neargye

Something like that, but with constexpr functions, and stl-like api (in C++17).

schaumb avatar Mar 11 '22 17:03 schaumb

https://github.com/Neargye/magic_enum/compare/master...schaumb:containers?expand=1

I started my own solution. Currently I only created constexpr magic_enum::containers::array<E, V> and magic_enum::containers::bitset<E> (std::bitset is not constexpr in latest standard)

bitset can be useful to transform not flag enums to 'flagged'.

I think other array constructions (which contains enums as parameter) can be define.

schaumb avatar May 23 '22 18:05 schaumb

FYI, hope bitset will be constexpr soon

Could you please make a PR, so it will be more convenient to check?

Neargye avatar May 23 '22 18:05 Neargye

today's conclusion: containers::map<E, mapped_type>::insert can be constexpr in c++17 only if any of the following condition is met to mapped_type:

  • trivially_assignable (union)
  • default_constructible (array)
  • has constructor which can be called with default constructed arguments (array)
  • explicitly grant an object as "default/invalid" element (array)

note0: (union) procedure will be the closest to std::map note1: (array) procedure will create mapped_type objects for all enum value at construction time. note2: std::map::operator[] and containers::map<E, mapped_type>::operator[] are requires mapped_type to be default_constructible

schaumb avatar May 24 '22 17:05 schaumb

You might want to have a look at https://github.com/Julien-Blanc-tgcm/indexed_array . I just added magic_enum support, and i think it provides what you want (unless you need iteration on both the key and the value, which is not yet provided)

Julien-Blanc-tgcm avatar Jun 29 '22 11:06 Julien-Blanc-tgcm

Thanks @Julien-Blanc-tgcm , It is a nice library.

Why is the iterators and the modification functions are not constexpr? What if Value is not default constructible?

I started to implement not only enum_array, but enum_map, enum_bitset, enum_set.

schaumb avatar Jun 30 '22 07:06 schaumb

Thanks for spotting the missing constexpr. It may be better to discuss this in indexed_array issue tracker, though. As for non default constructible values this is not an issue if they are provided at initialization (just like a plain std::array).

Julien-Blanc-tgcm avatar Jun 30 '22 10:06 Julien-Blanc-tgcm

Closed by https://github.com/Neargye/magic_enum/pull/187

Neargye avatar Feb 06 '23 13:02 Neargye