C++ Library Extensions 2022.12.09
To help learn modern C++ programming
039-reverse_for.cpp
Go to the documentation of this file.
1#include <tpf_output.hpp>
2
3/*
4 In this episode, we will learn one of the most important
5 and fundamental concepts regarding C++ Template Parameter.
6
7 For example,
8
9 template<typename Type>
10 class TemplateClass
11 {
12 Type m_member; // this m_member can be of ANY TYPE.
13 };
14
15 template<typename Type>
16 class LvalueTemplateClass
17 {
18 Type& m_member; // this m_member always ends up with lvalue reference
19 // it can be const lvalue reference or non-const lvalue reference
20 };
21
22 template<typename Type>
23 class RvalueTemplateClass
24 {
25 Type&& m_member; // this m_member can be either Lvalue Reference
26 // or Rvalue Reference.
27 };
28
29 template<typename Type>
30 void function_with_plain_T(Type arg) // "In Type arg," there is no declarator
31 {
32 the type of arg can be of ANY TYPE.
33 it can be lvalue reference, rvalue reference, or just plain type.
34
35 The type of Type and the type of arg are always the same, identical.
36 }
37
38 template<typename Type>
39 void function_with_lvalue_reference(Type& arg) // In Type& arg, & is called lvalue reference declarator
40 {
41 the type of arg is always lvalue reference.
42
43 the type of Type and the type of arg can be different.
44 They are always different.
45 }
46
47 template<typename Type> // we call Type as template parameter
48 void function_with_rvalue_reference(Type&& arg) // we call arg as a function-call parameter
49 // In Type&& arg, && is called rvalue reference declarator
50 {
51 the type of arg can be either lvalue reference, rvalue reference,
52 and arg can never be a plain type.
53
54 Don't get confused the type of Type, and the type of arg.
55
56 The type of Type and the type of arg can be the same or different.
57
58 When we test the type name of a Type, we can use
59
60 Tpf_GetTypeName(Type).
61
62 If we want to test the type name of an object (or variable),
63 we can use
64
65 Tpf_GetTypeCategory(arg).
66
67 Always test the types of Type or arg using
68 Tpf_GetTypeName() or Tpf_GetTypeCategory()
69 }
70*/
71
72/*
73 When you do template metaprogramming, or using C++ type functions in the #include<type_traits>,
74 never trust your intuition. Always test the type functions from C++ Standard Library,
75 using Tpf_GetTypeName() and Tpf_GetTypeCategory()
76 */
79
81{
82 // v is lvalue std::vector<int>
83 auto v = tpf::make_vector(1, 2, 3, 4, 5, 6, 7, 8, 9);
84
85 // range-based for
86 for(auto& e: v)
87 {
88 stream << e << ", ";
89 }
90
91 stream << endl;
92
93 for(auto& e: tpf::reverse(v) // C++ STL Container classes
94 )
95 {
96 stream << e << ", ";
97 }
98
99 stream << endl;
100
101 // prime numbers less than 20
102 // array is a static C++ array
103 int array[]{2, 3, 5, 7, 11, 13, 17, 19};
104
105 for(auto& e: array)
106 {
107 stream << e << ", ";
108 }
109
110 stream << endl;
111
112 for(auto& e: tpf::reverse(array) // this function handles for static array,
113 // array is of type int(&)[7]
114 )
115 {
116 stream << e << ", ";
117 }
118
119 stream << endl;
120
121 for(auto& e: {2, 4, 6, 8, 10})
122 {
123 stream << e << ", ";
124 }
125
126 stream << endl;
127
128 for(auto& e: tpf::reverse(2, 4, 6, 8, 10) // this reverse() creates a vector
129 // this vector is a pure rvalue
130 )
131 {
132 stream << e << ", ";
133 }
134
135 stream << endl;
136}
137
138template<typename Type>
139bool is_parameter_array(Type param)
140{
141 stream << "The type of Type: "
142 << Tpf_GetTypeName(Type) << endl;
143
144 return std::is_array_v<Type>;
145}
146
147template<typename Type>
148bool is_array(Type&& param)
149{
150 stream << "The type of Type: "
151 << Tpf_GetTypeName(Type) << endl;
152
153 return std::is_array_v<Type>;
154}
155
156template<typename Type>
157constexpr bool is_array_type_v = std::is_array_v<std::remove_reference_t<Type>>;
158
159template<typename Type>
160bool is_array_fixed(Type&& param)
161{
162 return is_array_type_v<Type>;
163}
164
166{
167 int array[]{1, 2, 3};
168
169 stream << "Is array an array? " << is_parameter_array(array) << endl;
170
171 stream << "\nUsing is_array(), is array an array? "
172 << is_array(array) << endl;
173
174 stream << "\nUsing is_array(), is array an array? "
175 << is_array_fixed(array) << endl;
176}
177
178template<typename Type, typename... Types>
179void variadic_parametered_function(Type arg, Types... args)
180{
181 using types_of_Types = tpf::types::type_list_t<Type, Types...>;
182
183 using types_of_function_call_parameters =
184 tpf::types::type_list_t< decltype(arg), decltype(args)...>;
185
186 stream << "types_of_Types: " << types_of_Types{} << endl;
187
188 stream << "types_of_function_call_parameters: "
189 << types_of_function_call_parameters{} << endl;
190}
191
192template<typename Type, typename... Types>
194{
195 using types_of_Types = tpf::types::type_list_t<Type, Types...>;
196
197 using types_of_function_call_parameters =
198 tpf::types::type_list_t< decltype(arg), decltype(args)...>;
199
200 stream << "types_of_Types: " << types_of_Types{} << endl;
201
202 stream << "types_of_function_call_parameters: "
203 << types_of_function_call_parameters{} << endl;
204}
205
207{
208 variadic_parametered_function(1, 2.0f, 3.14);
209
210 stream << endl;
211
212 variadic_parametered_function("String", L"Wide string", 2.0f, 3.14);
213}
214
216{
217 int a = 1;
218 float f = 3.0f;
219
221
222 stream << endl;
223
224 variadic_forwarding_reference_parametered_function("String", L"Wide string", 1, a, 2.0f, f, 3.14);
225}
226
227int main()
228{
229 // test_reverse_range_based_for();
230
231 // test_is_parameter_array();
232
233 // test_variadic_parameters();
234
236}
void variadic_parametered_function(Type arg, Types... args)
void test_is_parameter_array()
void test_variadic_parameters()
bool is_array(Type &&param)
tpf::sstream stream
bool is_array_fixed(Type &&param)
void test_reverse_range_based_for()
void variadic_forwarding_reference_parametered_function(Type &&arg, Types &&... args)
void test_variadic_forwarding_reference_parameters()
auto endl
bool is_parameter_array(Type param)
constexpr bool is_array_type_v
int main()
decltype(auto) reverse(ContainerType &&container)
Definition: tpf_types.hpp:7959
decltype(auto) make_vector(Type &&arg, Types &&... args)
Definition: tpf_types.hpp:7911
constexpr auto endl
Definition: tpf_output.hpp:973
This type is used to manipulate type list.
Definition: tpf_types.hpp:956
Stream output operators << are implemented.
#define Tpf_GetTypeName(type_arg)
A macro that returns type_arg's string name.
Definition: tpf_types.hpp:1422