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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
#include <algorithm>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include <cstddef>
namespace enum_utils {
template <typename F>
const char *find (typename F::enum_type value) {
typename F::range_type range;
for (range = F::get_table(); range.first != range.second; ++range.first) {
if (range.first->second == value) break;
}
return (range.first != range.second) ? range.first->first : 0;
}
template <typename F>
typename F::enum_type
find (const std::string &name) {
typename F::range_type range;
for (range = F::get_table(); range.first != range.second; ++range.first) {
if (range.first->first == name) break;
}
return (range.first != range.second
? range.first->second
: typename F::enum_type());
}
template <typename T, std::size_t N>
std::size_t n_elements (const T (&) [N]) { return N; }
}
#define ELOI_COMMA ,
#define ELOI_SEMI ;
#define ELOI_MKENUM_ELMT(name, value) name value
#define ELOI_MKTABLE_ELMT(name, value) \
std::make_pair(static_cast<const char *>(#name), name)
#define ELOI_MKENUM(enum_name, enum_gen) \
enum enum_name { enum_gen(ELOI_MKENUM_ELMT, ELOI_COMMA) }
#define ELOI_MKTABLE(enum_name, enum_gen) \
struct enum_name##_table { \
typedef enum_name enum_type; \
typedef const std::pair<const char *, enum_type> item_type; \
typedef std::pair<item_type *, item_type *> range_type; \
static range_type get_table () { \
static const std::pair<const char *, enum_name> table[] = { \
enum_gen(ELOI_MKTABLE_ELMT, ELOI_COMMA) \
}; \
return range_type(table, \
table + enum_utils::n_elements(table)); \
} \
};
#define ELOI_MKFIND(enum_name, enum_gen) \
enum_name find_##enum_name (const std::string &name) { \
return enum_utils::find<enum_name##_table>(name); \
} \
const char *find_##enum_name (enum_name value) { \
return enum_utils::find<enum_name##_table>(value); \
}
#define ELOI_MKSTRMAP(enum_name, enum_gen) \
ELOI_MKENUM(enum_name, enum_gen); \
ELOI_MKTABLE(enum_name, enum_gen); \
ELOI_MKFIND(enum_name, enum_gen); \
enum { }
#define STRMAP_GENERATOR(F, sep) \
F(none, = 0) sep \
F(foo, = 1) sep \
F(bar, = 2) sep \
F(baz, = 4)
namespace strmap {
ELOI_MKSTRMAP(values, STRMAP_GENERATOR);
}
#include <iostream>
int main (int argc, char *argv[]) {
std::string s;
std::cin >> s;
switch (strmap::find_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::istringstream str(s);
int n;
if (str >> n) {
if (const char *name = strmap::find_values(strmap::values(n))) {
std::cout << "This is the " << name << " code!\n";
break;
}
}
std::cerr << "What?" << std::endl;
break;
}
}
}
|