strenum.cpp

(plain text)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// How to hax0r a switch statement to work with strings.
// Public domain. No warranty. Go nuts.

//////////////////////////////////////////////////////////////////////

#include <map>
#include <string>

#define ELOI_COMMA ,
#define ELOI_SEMI ;
#define ELOI_MKENUM_ELMT(name, value) name value
#define ELOI_MKTABLE_ELMT(enum_name, value) (*this)[#enum_name] = enum_name

#define ELOI_MKENUM(name, enumgen)			\
  enum name { enumgen(ELOI_MKENUM_ELMT, ELOI_COMMA) }

#define ELOI_MKTABLE(enum_name, enum_gen)			\
  enum_name lookup_##enum_name (const std::string &s) {		\
    static const struct table_type				\
      : public std::map<std::string, enum_name> {		\
      table_type () { enum_gen(ELOI_MKTABLE_ELMT, ELOI_SEMI); } \
    } table;							\
    table_type::const_iterator i = table.find(s);		\
    return (i != table.end()) ? i->second : enum_name();	\
  }

#define ELOI_MKSTRMAP(enum_name, enum_gen)				\
  ELOI_MKENUM(enum_name, enum_gen); ELOI_MKTABLE(enum_name, enum_gen)

//////////////////////////////////////////////////////////////////////

namespace strmap {
#define STRMAP_GENERATOR(F, sep)		\
  F(none, = 0) sep				\
  F(foo,  = 1) sep				\
  F(bar,  = 2) sep				\
  F(baz,  = 4)

  ELOI_MKSTRMAP(values, STRMAP_GENERATOR);
}

//////////////////////////////////////////////////////////////////////

#include <iostream>

int main (int argc, char *argv[]) {
  std::string s;
  std::cin >> s;

  switch (strmap::lookup_values(s)) {
  case strmap::foo:
    std::cout << "This is the foo code!" << std::endl;
    break;

  case strmap::bar:
    std::cout << "This is the bar code!" << std::endl;
    break;

  case strmap::baz:
    std::cout << "This is the baz code!" << std::endl;
    break;

  default:
    std::cerr << "What?" << std::endl;
    break;
  }
}