-
Notifications
You must be signed in to change notification settings - Fork 31
/
Copy pathintro.cpp
127 lines (104 loc) · 3.31 KB
/
intro.cpp
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
125
126
127
// MPark.Patterns
//
// Copyright Michael Park, 2017
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#include <mpark/patterns.hpp>
#include <cassert>
#include <iostream>
#include <optional>
#include <string>
#include <type_traits>
#include <utility>
#include <variant>
#include <vector>
#include <gtest/gtest.h>
auto fizzbuzz_v1() {
std::vector<std::variant<int, std::string>> result;
using namespace mpark::patterns;
for (int i = 1; i <= 100; ++i) {
match(i % 3, i % 5)(pattern(0, 0) = [&] { result.push_back("fizzbuzz"); },
pattern(0, _) = [&] { result.push_back("fizz"); },
pattern(_, 0) = [&] { result.push_back("buzz"); },
pattern(_, _) = [&] { result.push_back(i); });
}
return result;
}
auto fizzbuzz_v2() {
std::vector<std::variant<int, std::string>> result;
using namespace mpark::patterns;
for (int i = 1; i <= 100; ++i) {
IDENTIFIERS(x);
match(i)(
pattern(_).when(_ % 15 == 0) = [&] { result.push_back("fizzbuzz"); },
pattern(arg).when(arg % 3 == 0) = [&](auto) { result.push_back("fizz"); },
pattern(x).when(x % 5 == 0) = [&](auto) { result.push_back("buzz"); },
pattern(x) = [&](auto x) { result.push_back(x); });
}
return result;
}
int factorial(int n) {
using namespace mpark::patterns;
return match(n)(pattern(0) = [] { return 1; },
pattern(arg) = [](int n) { return n * factorial(n - 1); });
}
int fib_v0(int n) {
using namespace mpark::patterns;
assert(n >= 0);
return match(n)(
pattern(0) = [] { return 0; },
pattern(1) = [] { return 1; },
pattern(arg) = [](int n) { return fib_v0(n - 1) + fib_v0(n - 2); });
}
int fib_v1(int n) {
using namespace mpark::patterns;
IDENTIFIERS(x);
return match(n)(
pattern(x).when(x <= 0) = [](int) { return 0; },
pattern(1) = [] { return 1; },
pattern(x) = [](int x) { return fib_v1(x - 1) + fib_v1(x - 2); });
}
int fib_v2(int n) {
using namespace mpark::patterns;
return match(n)(
pattern(arg).when(arg < 0) = [](int) { return 0; },
pattern(arg(anyof(0, 1))) = [](int n) { return n; },
pattern(arg) = [](int n) { return fib_v2(n - 1) + fib_v2(n - 2); });
}
TEST(Intro, Fizzbuzz) {
EXPECT_EQ(fizzbuzz_v1(), fizzbuzz_v2());
}
TEST(Intro, Factorial) {
EXPECT_EQ(120, factorial(5));
EXPECT_EQ(3628800, factorial(10));
}
TEST(Intro, Fibonacci) {
EXPECT_EQ(55, fib_v0(10));
EXPECT_EQ(55, fib_v1(10));
EXPECT_EQ(55, fib_v2(10));
}
TEST(Intro, ExplicitReturnType) {
std::optional<double> o(4.2);
using namespace mpark::patterns;
auto x = match<int>(o)(
pattern(some(arg)) = [](double v) { return v; },
pattern(none) = [] { return 'A'; });
static_assert(std::is_same<decltype(x), int>::value, "");
EXPECT_EQ(4, x);
}
TEST(Intro, ExplicitReturnVoid) {
std::optional<double> o(4.2);
using namespace mpark::patterns;
match<void>(o)(
pattern(some(arg)) = [](double v) { return v; },
pattern(none) = [] { return 'A'; });
}
TEST(Intro, ExplicitReturnImplicitConversion) {
struct S {
S(long) { EXPECT_TRUE(true); }
explicit S(int) { EXPECT_TRUE(false); }
};
using namespace mpark::patterns;
match<S>(0)(pattern(_) = [] { return 42; });
}