-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathv04.cpp
More file actions
103 lines (87 loc) · 2.03 KB
/
v04.cpp
File metadata and controls
103 lines (87 loc) · 2.03 KB
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
#include "fluff.hpp"
namespace detail
{
template <typename Fn>
class DefaultCase
{
public:
explicit DefaultCase(Fn fn) : fn(fn) {}
bool supports(const std::type_info&) const { return true; }
Fn getFn() const { return fn; }
private:
Fn fn;
};
template <typename Fn>
class EmptyCase
{
public:
explicit EmptyCase(Fn fn) : fn(fn) {}
bool supports(const std::type_info& t) const { return t == typeid(void); }
Fn getFn() const { return fn; }
private:
Fn fn;
};
template <typename Result>
Result switchAnyImpl(boost::any& a, const std::type_info& t) {
assert(false && "No case matched.");
std::terminate();
}
template <typename Result, typename Case, typename... Cases>
Result switchAnyImpl(boost::any& a, const std::type_info& t,
Case c, Cases... cases) {
if (c.supports(t))
return c.getFn()();
return switchAnyImpl<Result>(a, t, cases...);
}
}
template <typename Result, typename... Cases>
Result switchAny(boost::any& a, Cases... cases)
{
return detail::switchAnyImpl<Result>(a, a.type(), cases...);
}
template <typename Fn>
detail::DefaultCase<Fn> defaultCase(Fn fn)
{
return detail::DefaultCase<Fn>(fn);
}
template <typename Fn>
detail::EmptyCase<Fn> emptyCase(Fn fn)
{
return detail::EmptyCase<Fn>(fn);
}
TEST(SwitchAny, usesDefaultCase)
{
boost::any a;
int result = switchAny<int>(a,
defaultCase([] { return 1; })
);
EXPECT_EQ(1, result);
}
TEST(SwitchAny, usesEmptyCaseForEmpty)
{
boost::any a;
int result = switchAny<int>(a,
emptyCase([] { return 2; }),
defaultCase([] { return 1; })
);
EXPECT_EQ(2, result);
}
TEST(SwitchAny, skipsEmptyCaseForNonEmpty)
{
boost::any a = 1;
int result = switchAny<int>(a,
emptyCase([] { return 2; }),
defaultCase([] { return 1; })
);
EXPECT_EQ(1, result);
}
TEST(SwitchAny, usesTypedCaseForFull)
{
boost::any a = 3;
int result = switchAny<int>(a,
typeCase<int>([](int& i) { return i; }),
emptyCase([] { return 2; }),
defaultCase([] { return 1; })
);
EXPECT_EQ(3, result);
}