How to optimally translate enumerations in the least amount of code?

It often happens that you have 2 enumerations that are equivalent, but numbered differently, and you need functions to translate elements from the first enumeration to the elements of the second and vice versa. This is usually very tedious for the code, and at any time when a new element is added, you should definitely add pairing to both the transformation and the inverse transformation function (this violates the DRY principle ).

What is the least error prone way to do this that still generates efficient code? I mention the effective part, because you could just create a bunch of pairs and put them in std :: maps if searching in runtime was not a problem. I would prefer something that would be as efficient as manually writing large switch statements going from one enumeration value to another.

With some stimulus preprocessor mask or pattern hackers, I'm sure you could come up with something where you would write a list of pairs and conversion and inverse transform functions would be created, but I'm not sure which approach prefers or why. Both methods have a reputation for slow compilation times and make it difficult to diagnose compilation errors. Or maybe some other approach completely?

+3
source share
6 answers

Are you looking for something like this? Not verified, but it should work.

(Standard warnings about premature optimization and the need for profiling, searching for std :: map might not be that bad, a giant switch table might not be that good.)

enum-impl.h:

// No include guard.
DEFINE_ENUM_PAIR(EGA_BRIGHT_RED, 12, HTML_RED, 0xff0000)
DEFINE_ENUM_PAIR(EGA_BRIGHT_BLUE, 9, HTML_BLUE, 0x0000ff)
DEFINE_ENUM_PAIR(EGA_BRIGHT_GREEN, 10, HTML_GREEN, 0x00ff00)
DEFINE_ENUM_PAIR(EGA_BLACK, 0, HTML_BLACK, 0x000000)

enums.cpp:

enum EgaColorType {
#define DEFINE_ENUM_PAIR(name1, value1, name2, value2) name1 = value1,
#include "enums-impl.h"
#undef DEFINE_ENUM_PAIR
};

enum HtmlColorType {
#define DEFINE_ENUM_PAIR(name1, value1, name2, value2) name2 = value2,
#include "enums-impl.h"
#undef DEFINE_ENUM_PAIR 
};

HtmlColorType ConvertEgaToHtml(EgaColorType c) {
switch (c) {
#define DEFINE_ENUM_PAIR(name1, value1, name2, value2) case name1: return name2;
#include "enums-impl.h"
#undef DEFINE_ENUM_PAIR
default: assert(false);
}

EgaColorType ConvertHtmlToEga(HtmlColorType c) {
switch (c) {
#define DEFINE_ENUM_PAIR(name1, value1, name2, value2) case name2: return name1;
#include "enums-impl.h"
#undef DEFINE_ENUM_PAIR
default: assert(false);
}
+2
source

Why doesn't the lookup table work? Why are you forced to use this giant switch statement

+2
source

, . , (, ).

- : .

, , .

. . , ++ 0x, , , , . , ..

, . , , .

. ( ) , , . , , "" Boost.Preprocessor.

:

DEFINE_CORRESPONDING_ENUMS(Server, Client,
  ((Server1, 1, Client1, 6))
  ((Server2, 2, Client2, 3))
  ((Common1, 4, Common1, 4))
  ((Common2, 5, Common2, 5))
  ((Server3, 7, Client3, 1))
);

, :

struct Server
{
  enum type { Server1 = 1, Server2 = 2, Common1 = 4, Common2 = 5, Server3 = 7 };
};

struct Client
{
  enum type { Client1 = 6, Client2 = 3, Common1 = 4, Common2 = 5, Client3 = 1 };
};

Server::type ServerFromClient(Client::type c)
{
  switch(c)
  {
  case Client1: return Server1;
  //...
  default: abort();
  }
}

Client::type ClientFromServer(Server::type s)
{
  //...
}

, . , , , ;)

:

  • - . .
  • 4-. , , Common. , (, ...), .
  • BOOST_PP_SEQ_FOREACH, .
  • BOOST_PP_CAT .
  • on gcc -E , ...
  • ,
+2

( ), . , , , . , _ , . , , , , , . , .

enum A
{
    MIN_A = 1,
    A_ATT_1 = 1,
    A_ATT_2 = 2,
    A_ATT_3 = 3,
    LAST_A
};

enum B
{
    MIN_B = 2
    B_ATT_2 = 2,
    B_ATT_1 = 4,
    B_ATT_3 = 5,
    LAST_B
};

B A_to_B[] =
{
    B_ATT_1,
    B_ATT_2,
    B_ATT_3
};

// Somewhere that will always run, as desired:
assert(LAST_A - MIN_A == sizeof(A_to_B) / sizeof(A_to_B[0]);

B from_A(A in)
{
    B ret = A_to_B[in - MIN_A];
    assert(ret != LAST_B);
    return ret;
}

A B_to_A[] =
{
    A_ATT_2,
    LAST_A,
    A_ATT_1,
    A_ATT_3
};

// Somewhere that will always run, as desired:
assert(LAST_B - MIN_B == sizeof(B_to_A) / sizeof(B_to_A[0]);

A from_B(B in)
{
    A ret = B_to_A[in - MIN_B];
    assert(ret != LAST_A);
    return ret;
}
+1

, ( , ), . , .

0

.

:

enum FirstSet { A=4, B=6, C=8, D=5 };
enum SecondSet { E=2, F=5, G=5, H=1 };

:

enum OneEnum { A, B, C, D };
enum TwoEnum { E, F, G, H };
int FirstSet[] = { 4, 6, 8, 5 };
int SecondSet[] = { 2, 5, 5, 1 };

, , , , O (n) , .

0

Source: https://habr.com/ru/post/1753548/


All Articles