1

I have an enum class something like this:

enum Type{ First, Second, Third};

I need to map them to some values, for example:

std::map<Type, std::pair<int, float>> mp{
    {First, std::make_pair(1, 8.)}, 
    {Second, std::make_pair(5, 2.)},
    {Third, std::make_pair(3, 7.)}
};

The problem with this approach is, when I want to add new values to the enum (let's say an element 'Fourth'), I have to update both the enum Type and the map. How to fix this problem?

  • 2
    @GSerg the proposed answer in that link does exactly what the OP of this question *doesn't* want to do - having to update the `map` manually when adding a new `enum` value. The only benefit to the linked answer is that it `assert`s if the `map` doesn't match the `enum` values, which at least produces an error message telling the user to update the `map`. – Remy Lebeau Oct 18 '21 at 23:06
  • 4
    If I'm understanding correctly that the problem is _updating two things that must stay synchronized_, perhaps this is a situation where [X-macros](https://stackoverflow.com/questions/6635851/real-world-use-of-x-macros) is appropriate. – Drew Dormann Oct 18 '21 at 23:10
  • 1
    Thanks Drew Dormann and Eugene. It seems X-Macros solves the problem. I'll try to make it work for my case. Never thought about using macros this way :) – Abdurasul Rakhimov Oct 18 '21 at 23:29
  • I tend to go to code generation for stuff like this once it gets big or risky enough. I'll have a file that describes the data and a small program that parses the data description and generates code to do the drudgework. The build system manages everything from there. If the data description has changed, regenerate the code. Compile it, link it. – user4581301 Oct 18 '21 at 23:32
  • Do you really need an enum type (i.e. `Type`) ? If so, do you need named values (i.e. `First`)? To me, it seems very artificial that you would a case where one need `enum` values for data that is changing... If the purpose of the `enum` is only to have a distinct type, the solution is much simpler that if you need named values. – Phil1970 Oct 19 '21 at 00:21

1 Answers1

2

You can populate the map at runtime instead of at compile-time, eg:

enum Type{ First, Second, Third, NumberOfTypes };

std::map<Type, std::pair<int, float>> mp;

...

// during program startup...
for(int i = First; i < NumberOfTypes; ++i) {
    mp.emplace(static_cast<Type>(i), std::make_pair(i, static_cast<float>(i)));
}

Online Demo

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 1
    I think you responded to OP example too literally. Filling map with 1,2,3 was just for illustration. – Eugene Oct 18 '21 at 23:24
  • Ah, sorry. This does not really solve my problem. Because the values do not always coincide with the position. It was just an example. – Abdurasul Rakhimov Oct 18 '21 at 23:24
  • The above still works fine if you keep your values in a separate container. Then you'd update the enum, and add a new value to the container, and the `for` loop will take care of adding the values together in your `map` - you only need to name the `enum` once – Tas Oct 18 '21 at 23:28
  • @Tas but I would still need to synchronize and update two things each time when I want to add new element to enum – Abdurasul Rakhimov Oct 18 '21 at 23:32