0

Let't suppose I have this code:

// the enumerator
enum class my_enum {
    ONE,
    TWO,
    THREE
};

// the function
template <my_enum E>
int foo() {
    return 0;
}

// a specialization
template<>
int foo<my_enum::TWO>() {
    return 1;
}

I would like to write a bar function that specializes foo for each element of my_enum, and that calls, at run-time, one of those functions based on the value of an argument of bar. The simplest solution is to write a switch and manually adding all the cases:

int bar(my_enum value) {
    switch (value) {
    using m = my_enum;
    case m::ONE:
        return foo<m::ONE>();
    case my_enum::TWO:
        return foo<m::TWO>();
    case my_enum::THREE:
        return foo<m::THREE>();
    }
}

with some additional tricks to handle a unexpected value adding a default value of the switch. Unfortunately, for very long enumerators this solution brings to very long and redundant code, that is difficult to be maintained.

Is there any metaprogramming solution to simplify this code, for example using Boost Hana or Boost MPL?

Giovanni Cerretani
  • 1,693
  • 1
  • 16
  • 30
  • related/maybe dupe: https://stackoverflow.com/questions/8498300/allow-for-range-based-for-with-enum-classes. There is a MPL answer there. – NathanOliver Jan 03 '20 at 13:39

1 Answers1

1

If the enum values are, as in your example, starting from zero and consecutive... given an helper function as follows

template <std::size_t ... Is>
std::array<int(*)(void), sizeof...(Is)>
    getFuncArray (std::index_sequence<Is...>)
 { return {{ &foo<static_cast<my_enum>(Is)>... }}; }

you can add, in bar(), a static array of functions and call the correct one according the input.

I mean

int bar (my_enum value)
 {
   static auto const arrF
      = getFuncArray(std::make_index_sequence<
                        1u+static_cast<std::size_t>(my_enum::THREE)>{});

   return arrF[static_cast<std::size_t>(value)]();
 }
max66
  • 65,235
  • 10
  • 71
  • 111
  • The logic is fine but, unfortunately, it works only if the enumeration starts from zero and is consecutive :( – Giovanni Cerretani Jan 15 '20 at 11:04
  • @GiovanniCerretani - Unfortunately. You can also use a map, instead of an array, when the enum values are sparse; but I don't know how initialize the map. – max66 Jan 15 '20 at 11:39