C++ Library Extensions 2022.12.09
To help learn modern C++ programming
037-make_vector.cpp
Go to the documentation of this file.
1#include <tpf_output.hpp>
2
5
7{
8 // make_container() creates either vector or tuple
9 auto v = tpf::make_container(1, 2, 3, 4.0f, 5.0, 6, 7, 8, 9, 10);
10
11 stream << "The type of v: " << Tpf_GetTypeCategory(v) << endl;
12
13 stream << "v = " << v << endl;
14
15 stream << "reversed v = " << tpf::reverse(v).clone() << endl;
16
17 for(auto& e: v)
18 {
19 stream << e << ", " ;
20 }
21
22 stream << endl;
23
24 for(auto& e: tpf::reverse(v) )
25 {
26 stream << e << ", " ;
27 }
28
29 stream << endl;
30}
31
33{
34 for(auto& e: tpf::reverse(2, 3, 5, 7, 11, 13, 17, 19))
35 {
36 stream <<e << ", ";
37 }
38
39 stream << endl;
40
41 std::list<int> lst{1, 2, 3, 4, 5};
42
43 for(auto& e: lst)
44 {
45 stream << e << ", ";
46 }
47
48 stream << endl;
49
50 for(auto& e: tpf::reverse(lst))
51 {
52 ++e;
53 stream << e << ", ";
54 }
55
56 stream << endl;
57
58 for(auto& e: lst)
59 {
60 stream << e << ", ";
61 }
62
63 stream << endl;
64
65}
66
68{
69 // make_variants() creates a vector
70 // when arguments have a common type
71 // in this case, the common type of 1, 2, 3.0f, 5.0 is double
72 // so, it creates std::vector<double>
73 auto c1 = tpf::make_variants(1, 2, 3.0f, 5.0);
74
75 stream <<"Type of c1: " << Tpf_GetTypeCategory(c1) << endl;
76 stream <<"The contents of c1: " << c1 << endl;
77
78 // when arguments do not have common type,
79 // then make_variants() creates a vector<std::variant>
80 auto c2 = tpf::make_variants(2, 3.0f, "James Dean", std::string("Sophie Turner"));
81
82 stream <<"Type of c2: " << Tpf_GetTypeCategory(c2) << endl;
83 stream <<"The contents of c2: " << c2 << endl;
84
85 // when arguments have a common type,
86 // make_container() creates std::vector<common type>
87 // otherwise, creates std::tuple<>
88 // in this case, the common type is double
89 // so, it creates std::vector<double>
90 auto c3 = tpf::make_container(1, 2.0f, 3.0);
91
92 stream <<"Type of c3: " << Tpf_GetTypeCategory(c3) << endl;
93 stream <<"The contents of c3: " << c3 << endl;
94
95 // when arguments do not have common type,
96 // make_container() creates a tuple
97 auto c4 = tpf::make_container("James Dean", "Sophie Turner", 3.14);
98
99 stream <<"Type of c4: " << Tpf_GetTypeCategory(c4) << endl;
100 stream <<"The contents of c4: " << c4 << endl;
101}
102
103template<typename Type>
104decltype(auto) decay(Type&& arg)
105{
106 using type = std::remove_reference_t<Type>;
107
108 if constexpr(std::is_array_v<type> || std::is_function_v<type>)
109 {
110 // std::cout << "Decaying Type " << std::endl;
111
112 return (std::decay_t<type>)(arg);
113 }
114 else
115 {
116 // std::cout << "Decaying Type Bypassed " << std::endl;
117 return std::forward<Type>(arg);
118 }
119}
120
122{
123 int array[]{1, 2, 3};
124
125 stream << "Type of array: " << Tpf_GetTypeCategory(array) << endl;
126
127 auto decayed_array = decay(array);
128
129 stream <<"Type of decayed_array: " << Tpf_GetTypeCategory(decayed_array) << endl;
130}
131
132// this type function
133// decays, remove reference, remove const volatile
134template<typename Type>
135using decay_remove_cv_ref_t = std::remove_cv_t<std::remove_reference_t<std::decay_t<Type>>>;
136
137template<typename Type, typename... Types>
138auto make_vector(Type&& arg, Types&&... args)
139{
140 // we test if the types of arg, args... are the same
141 constexpr auto all_types_same
142 = tpf::types::is_same_v<decay_remove_cv_ref_t<Type>, decay_remove_cv_ref_t<Types>...>;
143
144 // we test if there exists a common for arg and args...
145 constexpr auto common_type_exists
146 = tpf::types::common_type_v<decay_remove_cv_ref_t<Type>, decay_remove_cv_ref_t<Types>...>;
147
148 static_assert(common_type_exists, "Common Type Does Not Exist");
149
150 if constexpr(all_types_same)
151 {
153 using container_t = std::vector<element_t>;
154
155 return container_t{ std::forward<Type>(arg),
156 std::forward<Types>(args)...};
157 }
158 else
159 {
160 // common type exists
161 using common_type =
163
164 // if all types are of integral type
165 if constexpr(tpf::types::is_integral_v<common_type>)
166 {
167 // we test all elements are of unsigned type
168 constexpr auto all_unsigned
169 = tpf::types::are_unsigned_integrals_v<decay_remove_cv_ref_t<Type>, decay_remove_cv_ref_t<Types>...>;
170
171 if constexpr(all_unsigned)
172 {
173 using element_t = common_type;
174 using container_t = std::vector<element_t>;
175
176 return container_t{ static_cast<element_t>(arg),
177 static_cast<element_t>(args)...};
178 }
179 else
180 {
181 using element_t = std::make_signed_t<common_type>;
182 using container_t = std::vector<element_t>;
183
184 return container_t{ static_cast<element_t>(arg),
185 static_cast<element_t>(args)...};
186 }
187 }
188 else
189 {
190 using element_t = common_type;
191 using container_t = std::vector<element_t>;
192
193 return container_t{ static_cast<element_t>(arg),
194 static_cast<element_t>(args)...};
195 }
196 }
197}
198
200{
201 auto v1 = make_vector(1, 2, 3, 4, 5.0f, 6.0);
202
203 stream << "Type of v1: " << Tpf_GetTypeCategory(v1) << endl;
204 stream <<" v1 = " << v1 << endl;
205
206 // when arguments are composed of signed and unsigned,
207 // the common type is NOT unsigned, but signed
208 auto v2 = make_vector(2, 3, 4, 5u);
209
210 stream << "Type of v2: " << Tpf_GetTypeCategory(v2) << endl;
211 stream <<" v2 = " << v2 << endl;
212
213}
214
215template<typename Type, typename... Types>
216auto make_container(Type&& arg, Types&&... args)
217{
218 // we test if the types of arg, args... are the same
219 constexpr auto all_types_same
220 = tpf::types::is_same_v<decay_remove_cv_ref_t<Type>, decay_remove_cv_ref_t<Types>...>;
221
222 // we test if there exists a common for arg and args...
223 constexpr auto common_type_exists
224 = tpf::types::common_type_v<decay_remove_cv_ref_t<Type>, decay_remove_cv_ref_t<Types>...>;
225
226 if constexpr(all_types_same || common_type_exists)
227 {
228 return make_vector( std::forward<Type>(arg), std::forward<Types>(args)...);
229 }
230 else
231 {
232 // when arguments do not have common type
233 // we create a tuple
234 return std::make_tuple(std::forward<Type>(arg), std::forward<Types>(args)...);
235 }
236}
237
238
240{
241 auto v1 = make_container(1, 2, 3, 4, 5.0f, 6.0);
242
243 stream << "Type of v1: " << Tpf_GetTypeCategory(v1) << endl;
244 stream <<" v1 = " << v1 << endl;
245
246 // when arguments are composed of signed and unsigned,
247 // the common type is NOT unsigned, but signed
248 auto v2 = make_container("Sophie Turner", 2, 3, 4, 5u);
249
250 stream << "Type of v2: " << Tpf_GetTypeCategory(v2) << endl;
251 stream <<" v2 = " << v2 << endl;
252
253}
254
255int main()
256{
258
260
262
263 test_decay();
264
266
268}
void test_make_vector()
void test_reverse_range_for()
void test_make_variants_containers()
void test_reverse_range_based_for_loop()
tpf::sstream stream
std::remove_cv_t< std::remove_reference_t< std::decay_t< Type > > > decay_remove_cv_ref_t
void test_make_container()
auto make_container(Type &&arg, Types &&... args)
auto endl
void test_decay()
int main()
decltype(auto) decay(Type &&arg)
auto make_vector(Type &&arg, Types &&... args)
constexpr auto make_tuple(ArgTypes &&... args) noexcept
Definition: cpg_types.hpp:2704
hidden::common_type_t< Types... > common_type_t
Definition: tpf_types.hpp:5122
decltype(auto) make_container(Type &&arg, Types &&... args)
Definition: tpf_types.hpp:7923
decltype(auto) reverse(ContainerType &&container)
Definition: tpf_types.hpp:7959
constexpr auto endl
Definition: tpf_output.hpp:973
decltype(auto) make_variants(Type &&arg, Types &&... args)
Definition: tpf_types.hpp:7951
Stream output operators << are implemented.
#define Tpf_GetTypeCategory(instance_arg)
A macro that returns instance_arg's type category string name.
Definition: tpf_types.hpp:1428