C++ Library Extensions 2022.12.09
To help learn modern C++ programming
004-preliminary_debugging.cpp
Go to the documentation of this file.
1#include <tpf_output.hpp>
2
3// note that sstream is a std::ostringstream based stream class
4// that means we have flush to print out the result,
5// otherwise we cannot see anything.
7auto nl = tpf::nl; // new line without flushing for performance reason, or to use the stream as string.
8auto flush = tpf::flush; // flush out the stream to console without trailing newline.
9auto endl = tpf::endl; // flush out the stream with a trailing new line.
10
11template<typename Type>
12Type increment(Type arg) // note arg is template parameter
13{ // but they are not template-parameter pack
14 return arg + 1;
15}
16
17template<typename Type, typename... Types>
18void example_for_template_parameter_pack_expansion(Type arg, Types... args) // args is a template parameter pack
19{
20 auto v1 = std::vector<Type>{ arg, args... };
21 auto v2 = std::vector<Type>{ increment(arg), increment(args)... };
22 auto v3 = std::vector<Type>{ static_cast<Type>(arg), static_cast<Type>(args)... };
23 auto v4 = std::vector<Type>{ increment(static_cast<Type>(arg)), increment( static_cast<Type>(args) )... };
24
25 stream <<"v1 = " << v1 << nl;
26 stream <<"v2 = " << v2 << nl;
27 stream <<"v3 = " << v3 << nl;
28 stream <<"v4 = " << v4 << nl << flush;
29}
30
31/*
32 GNU C++/clang++ strictly follows C++ Standard Specifications.
33 In case of Microsoft compiler, it has more relaxed syntax.
34
35 In a net shell, try to follow Standard Specification for maximum compability
36 as well as correct behavior of your compiler.
37*/
38
39// this is now forward declaration of template function
40template<typename Type>
41void print_out_parameter_packs(Type arg);
42
43// this function can take 1 or more
44template<typename Type, typename... Types>
45void print_out_parameter_packs(Type arg, Types... args)
46{
47 if(sizeof...(Types) == 0) // sizeof...(Types) == sizeof...(args)
48 {
50 }
51 else
52 {
53 // the count of the parameter pack args is not zero
54 stream << arg << ", ";
55
56 // the count of args is not zero means it has 1 or more parameters
58 }
59}
60
62
63// Put more code in this section
64
66
67template<typename Type>
69{
70 stream << arg << endl;
71}
72
73/*
74 To address this ugly syntax regarding to template parameter pack expansion,
75 C++ Standard Committee introduced if constexpr construct as below
76*/
77
78template<typename Type, typename... Types>
79void example_of_if_constexpr(Type arg, Types... args)
80{
81 // if constexpr() was introduced to C++17 Standard
82 if constexpr(sizeof...(args) == 0) // if constexpr(const expression)
83 // sadly, the term "const expression" is misnomer
84 // it should be better called "compile-time expression"
85
86 {
87 // the parameter pack args... has zero elements
88 stream << arg << endl;
89 }
90 else
91 {
92 // the count of the parameter pack args... is one or more
93 stream << arg << ", ";
95 }
96}
97
98template<typename Type>
99Type square_me(Type arg)
100{
101 return arg * arg;
102}
103
104template<typename Type, typename... Types>
106{
107 // if constexpr() was introduced to C++17 Standard
108 if constexpr(sizeof...(args) == 0)
109 {
110 // the parameter pack args... has zero elements
111 stream << square_me(arg) << endl;
112 }
113 else
114 {
115 // the count of the parameter pack args... is one or more
116 stream << square_me(arg) << ", ";
118 }
119}
120
121template<typename Type, typename... Types>
122void example_of_pack_expansion(Type arg, Types... args)
123{
125}
126
127/*
128 Fold Expression was introduced to C++17 Standard.
129 It can be sometimes very handy when working with parameter packs.
130*/
131
132template<typename Type, typename... Types>
133Type divide_using_fold_exression(Type first, Types... args)
134{
135 // fold expression should be enclosed with parentheses as below.
136 return ( first / ... / args );
137
138 // ((first / next arg) / nnext arg) / nnnext arg ....
139 // where arg is an element in args...
140}
141
143{
144 auto rlt = divide_using_fold_exression(2*3*5, 2, 3);
145 // ( (2*3*5 / 2) / 3 ) == 5
146
147 stream <<"( (2*3*5 / 2) / 3 ) = " << rlt << endl;
148}
149
150template<typename Type, typename... Types>
152{
153 // fold expression should be enclosed with parentheses as below.
154 return ( square_me(first) / ... / square_me(args) );
155
156 // ((first / next arg) / nnext arg) / nnnext arg ....
157 // where arg is an element in args...
158}
159
160
162{
164 // ( ( (2*3*5)^2 / 2^2) / 3^2 ) == 5^2
165
166 stream <<"( ( (2*3*5)^2 / 2^2) / 3^2 ) = " << rlt << endl;
167}
168
169template<typename Type, typename... Types>
170void divide_fold_exression_with_pack_expansion(Type first, Types... args)
171{
172 stream << "Result: "
174 << endl;
175}
176
177/*
178 Variadic Macro was first introduced to C++11 Standard.
179*/
180
181// do not put semicolon at the end of macro defintion
182#define VeryUglyName_SquareFoldExpression(first, ...) divide_fold_exression_with_pack_expansion(first, __VA_ARGS__)
183
184int main()
185{
186 // example_for_template_parameter_pack_expansion(0, 1, 2, 3, 4, 5);
187 // print_out_parameter_packs(0, 1, 2, 3, 4, 5);
188
189 // example_of_if_constexpr(0, 1, 2, 3, 4, 5);
190
191 // example_of_if_constexpr_with_pack_expansion(0, 1, 2, 3, 4, 5);
192 // example_of_pack_expansion(0, 1, 2, 3, 4, 5);
193
194 // example_fold_expression();
198}
void example_of_pack_expansion(Type arg, Types... args)
void print_out_parameter_packs(Type arg)
tpf::sstream stream
void example_for_template_parameter_pack_expansion(Type arg, Types... args)
#define VeryUglyName_SquareFoldExpression(first,...)
void divide_fold_exression_with_pack_expansion(Type first, Types... args)
void example_with_pack_expansion_using_fold_exression()
void example_of_if_constexpr_with_pack_expansion(Type arg, Types... args)
void example_of_if_constexpr(Type arg, Types... args)
Type increment(Type arg)
Type divide_using_fold_exression_with_pack_expansion(Type first, Types... args)
Type divide_using_fold_exression(Type first, Types... args)
Type square_me(Type arg)
void example_fold_expression()
constexpr auto flush
Definition: tpf_output.hpp:970
constexpr auto endl
Definition: tpf_output.hpp:973
constexpr auto nl
Definition: tpf_output.hpp:971
Stream output operators << are implemented.