-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathMetaProgramming01.cpp
More file actions
148 lines (124 loc) · 4.91 KB
/
MetaProgramming01.cpp
File metadata and controls
148 lines (124 loc) · 4.91 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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// =====================================================================================
// MetaProgramming01.cpp // Metaprogramming: Part I
// =====================================================================================
module modern_cpp:metaprogramming;
namespace Metaprogramming {
template <long N>
struct Factorial {
static constexpr long result = N * Factorial<N - 1>::result;
};
template <>
struct Factorial<1> {
static constexpr long result = 1;
};
static void test_01() {
std::cout << Factorial<1>::result << std::endl;
std::cout << Factorial<2>::result << std::endl;
std::cout << Factorial<3>::result << std::endl;
std::cout << Factorial<4>::result << std::endl;
std::cout << Factorial<5>::result << std::endl;
std::cout << Factorial<6>::result << std::endl;
std::cout << Factorial<7>::result << std::endl;
std::cout << Factorial<8>::result << std::endl;
std::cout << Factorial<9>::result << std::endl;
std::cout << Factorial<10>::result << std::endl;
std::cout << Factorial<11>::result << std::endl;
std::cout << Factorial<12>::result << std::endl;
//std::cout << Factorial<13>::result << std::endl;
//std::cout << Factorial<14>::result << std::endl;
//std::cout << Factorial<15>::result << std::endl;
//std::cout << Factorial<16>::result << std::endl;
//std::cout << Factorial<17>::result << std::endl;
}
// =================================================================================
template <std::size_t N, std::size_t D>
struct Frac {
static constexpr std::size_t Num = N;
static constexpr std::size_t Den = D;
};
template <std::size_t N, typename F>
struct ScalarMultiplication {
using result = Frac<N * F::Num, F::Den>;
};
static void test_02() {
using TwoThirds = Frac<2, 3>;
using FourThirds = ScalarMultiplication<2, TwoThirds>::result;
std::cout << FourThirds::Num << "/" << FourThirds::Den << std::endl;
}
template <std::size_t X, std::size_t Y>
struct GGT {
static constexpr std::size_t result = GGT<Y, X % Y>::result;
};
template <std::size_t X>
struct GGT<X, 0> {
static constexpr std::size_t result = X;
};
template <typename F>
struct FracNormalizedVerbose {
static constexpr std::size_t ggt = GGT<F::Num, F::Den>::result;
static constexpr std::size_t newNum = F::Num / ggt;
static constexpr std::size_t newDen = F::Den / ggt;
using result = Frac<newNum, newDen>;
};
template <typename F>
struct FracNormalized {
static constexpr std::size_t ggt = GGT<F::Num, F::Den>::result;
using result = Frac<F::Num / ggt, F::Den / ggt>;
};
static void test_03() {
using Four = Frac<16, 4>;
using FourNormalized = FracNormalizedVerbose<Four>::result;
std::cout << FourNormalized::Num << "/" << FourNormalized::Den << std::endl;
using Eight = Frac<32, 4>;
using EightNormalized = FracNormalized<Eight>::result;
std::cout << EightNormalized::Num << "/" << EightNormalized::Den << std::endl;
}
template <typename X1, typename Y1>
struct SameBase {
using X = typename ScalarMultiplication<Y1::Den, X1>::result;
using Y = typename ScalarMultiplication<X1::Den, Y1>::result;
};
template <typename X, typename Y>
struct Sum {
using Base = SameBase<X, Y>;
static constexpr std::size_t Num = Base::X::Num + Base::Y::Num;
static constexpr std::size_t Den = Base::X::Den * Base::Y::Den;
using result = typename FracNormalized<Frac<Num, Den>>::result;
};
static void test_04() {
using Frac1 = Frac<1, 3>;
using Frac2 = Frac<4, 7>;
using Result = Sum<Frac1, Frac2>::result;
std::cout << Result::Num << "/" << Result::Den << std::endl;
}
// =================================================================================
template <long N>
struct E {
// e = 1/0! + 1/1! + 1/2! + ...
static constexpr long Den = Factorial<N>::result;
using Term = Frac<1, Den>;
using NextTerm = typename E<N - 1>::result;
using result = typename Sum<Term, NextTerm>::result;
};
template <>
struct E<0> {
using result = Frac<1, 1>;
};
static void test_05() {
using X = E<8>::result;
std::cout << "e = " << (1.0 * X::Num / X::Den) << std::endl;
std::cout << "e = " << X::Num << "/" << X::Den << std::endl;
}
}
void main_metaprogramming_01()
{
using namespace Metaprogramming;
test_01();
test_02();
test_03();
test_04();
test_05();
}
// =====================================================================================
// End-of-File
// =====================================================================================