- Notifications
You must be signed in to change notification settings - Fork 75
/
Copy pathdispatch.cxx
110 lines (91 loc) · 2.96 KB
/
dispatch.cxx
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
#include"../include/tuple.hxx"
#include"../include/enums.hxx"
template<
size_t I,
template<typename...> classclient_temp,
typename... types_t,
typename... enums_t,
typename... args_t
>
autodispatch_inner(tuple_t<enums_t...> e, args_t&&... args) {
ifconstexpr(I == sizeof...(enums_t)) {
// Instantiate the client class template.
return client_temp<types_t...>().go(std::forward<args_t>(args)...);
} else {
switch(get<I>(e)) {
static_assert(std::is_enum<enums_t...[I]>::value);
// Forward to the next level.
@meta forenum(autoe2 : enums_t...[I])
casee2:
return dispatch_inner<
I + 1,
client_temp,
types_t..., // Expand the old types
@enum_type(e2) // Add this as a new type
>(e, std::forward<args_t>(args)...);
}
}
}
template<
template<typename...> classclient_temp,
typename... enums_t,
typename... args_t
>
autodispatch(tuple_t<enums_t...> e, args_t&&... args) {
return dispatch_inner<0, client_temp>(e, std::forward<args_t>(args)...);
}
// Application code
structcircle { doubleval() const { return10; } };
structsquare { doubleval() const { return20; } };
structoctagon { doubleval() const { return30; } };
enumtypenameclassshapes_t {
circle = circle,
square = square,
octagon = octagon,
};
structred { doubleval() const { return1; } };
structgreen { doubleval() const { return2; } };
structyellow { doubleval() const { return3; } };
enumtypenameclasscolors_t {
red = red,
green = green,
yellow = yellow,
};
structsolid { doubleval() const { return .1; } };
structhatch { doubleval() const { return .2; } };
structhalftone { doubleval() const { return .3; } };
enumtypenameclassfills_t {
solid = solid,
hatch = hatch,
halftone = halftone,
};
template<typenameshape_obj_t, typenamecolor_obj_t,
typenamefill_obj_t>
structshape_computer_t {
shape_obj_t shape;
color_obj_t color;
fill_obj_t fill;
@meta printf("Instantiating { %s, %s, %s }\n", @type_string(shape_obj_t),
@type_string(color_obj_t), @type_string(fill_obj_t));
doublego(double x) {
return (x * shape.val() + color.val()) * fill.val();
}
};
intmain(int argc, char** argv) {
if(5 != argc) {
printf("Usage: dispatch shape-name color-name fill-name x\n");
exit(1);
}
// Meta-generated if-strcmp chain finds an enumerator from a string.
shapes_t shape = enum_from_name_error<shapes_t>(argv[1]);
colors_t color = enum_from_name_error<colors_t>(argv[2]);
fills_t fill = enum_from_name_error<fills_t>(argv[3]);
double x = atof(argv[4]);
// Use our tuple to hold the runtime enums.
tuple_t<shapes_t, colors_t, fills_t> key { shape, color, fill };
// Provide the enum tuple to select the object to instantiate and the
// numeric argument.
double y = dispatch<shape_computer_t>(key, x);
printf("The dispatch result is %f\n", y);
return0;
}