-
Notifications
You must be signed in to change notification settings - Fork 73
/
choice5.cxx
54 lines (43 loc) · 1.58 KB
/
choice5.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
#feature on choice
#include <type_traits>
#include <iostream>
choice Foo {
x(int),
y(double),
z(const char*),
};
template<typename T> requires (T~is_enum)
const char* enum_to_string(T e) noexcept {
return T~enum_values == e ...?
T~enum_names :
"unknown enum of type {}".format(T~string);
}
int main() {
// "alternatives" is an enum member of Foo.
static_assert(Foo::alternatives~is_enum);
// It has enumerators for each choice alternative.
std::cout<< "alternatives enumerators:\n";
std::cout<< " {} = {}\n".format(Foo::alternatives~enum_names,
Foo::alternatives~enum_values~to_underlying) ...;
// Naming a choice alternative gives you back an enumerator.
static_assert(Foo::alternatives == decltype(Foo::x));
// Foo::y is an enumerator of type Foo::alternatives. But it's also
// how you construct choice types! The enumerator has been overloaded to
// work as an initializer.
// Foo::y is type Foo::alternatives.
static_assert(Foo::alternatives == decltype(Foo::y));
// Foo::y() is an initializer, so Foo::y() is type Foo.
static_assert(Foo == decltype(Foo::y()));
// Initialize a Foo object.
Foo obj = .y(3.14);
// .active is an implicit data member set to the active alternative.
// The type is Foo::alternatives.
std::cout<< "obj.active = "<< enum_to_string(obj.active)<< "\n";
// Compare an enumerator with the .active member to see what's active.
if(Foo::x == obj.active)
std::cout<< "x is active\n";
else if(Foo::y == obj.active)
std::cout<< "y is active\n";
else if(Foo::z == obj.active)
std::cout<< "z is active\n";
}