Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
tuple-helper-test.cpp
Go to the documentation of this file.
1/*
2 TupleHelper(Test) - verify helpers for working with tuples and type sequences
3
4 Copyright (C)
5 2009, Hermann Vosseler <Ichthyostega@web.de>
6
7  **Lumiera** is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License as published by the
9  Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version. See the file COPYING for further details.
11
12* *****************************************************************/
13
14
25#include "lib/test/run.hpp"
30#include "lib/format-string.hpp"
31#include "lib/format-cout.hpp"
32#include "lib/hetero-data.hpp"
34
35#include <string>
36
38using util::toString;
39using util::_Fmt;
40using std::is_same_v;
41using std::make_tuple;
42using std::get;
43
44namespace lib {
45namespace meta {
46namespace test {
47
48
49
50 namespace { // test data
51
52
53 typedef Types< Num<1>
54 , Num<3>
55 , Num<5>
57 typedef Types< Num<2>
58 , Num<4>
61
62
63
64 } // (End) test data
65
66
67
68 /*********************************************************************/
75 class TupleHelper_test : public Test
76 {
77 virtual void
85
86
91 void
93 {
94 typedef Types1::List L1;
95 typedef Types2::List L2;
96 typedef Types3::List L3;
97
98 DISPLAY (L1);
99 DISPLAY (L2);
100 DISPLAY (L3);
101
102 typedef Tuple<Types1> Tup1;
103 Tup1 tup1x (Num<1>(11), Num<3>(), 55);
104
105 DISPLAY (Tup1); // prints the type
106 DUMPVAL (Tup1()); // prints the contents
107 DUMPVAL (tup1x);
108
109 EXPECT (Types1, "-<1>-<3>-<5>-");
110 EXPECT (Tup1, "TUPLE-<1>-<3>-<5>-");
111 CHECK (get<2>(tup1x) == Num<5>{55});
112 CHECK (toString(tup1x) == "«tuple<Num<1>, Num<3>, Num<5> >»──({11},(3),{55})"_expect);
113 }
114
115
121 void
123 {
124 using L1 = Types1::List; // ... start from existing Typelist...
125
126 using T_L1 = Tuple<L1>; // derive a tuple type from this typelist
128 // extract the underlying type sequence
129 EXPECT (T_L1, "TUPLE-<1>-<3>-<5>-");
130 EXPECT (Seq1, "-<1>-<3>-<5>-");
131
132 T_L1 tup1; // can be instantiated at runtime (and is just a std:tuple)
133 CHECK (toString(tup1) == "«tuple<Num<1>, Num<3>, Num<5> >»──((1),(3),(5))"_expect);
134
136 // another ListType based tuple created by prepending
137 EXPECT (Prepend, "TUPLE-<i>-<1>-<3>-<5>-");
138
139 Prepend prep (22, 11,33,Num<5>());
140 CHECK (toString(prep) == "«tuple<int, Num<1>, Num<3>, Num<5> >»──(22,{11},{33},(5))"_expect);
141
142 using NulT = Tuple<Types<> >; // plain-flat empty Tuple
143 using NulL = Tuple<Nil>; // list-style empty Tuple
144
145 NulT nulT; // and these, too, can be instantiated
146 NulL nulL;
147 CHECK (toString(nulT) == "«tuple<>»──()"_expect);
148 CHECK (toString(nulL) == "«tuple<>»──()"_expect);
150
151 using S4 = struct{int a,b,c,d;}; // expect this to have the same memory layout
152 CHECK (sizeof(S4) == sizeof(prep));
153 CHECK (1 == sizeof(nulL)); // ...minimal storage, as expected
154
155
160
161 cout << tup1 <<endl // these automatically use our generic string conversion
162 << prep <<endl
163 << nulL <<endl;
164
165 cout << showSizeof(tup1) <<endl
166 << showSizeof(prep) <<endl
167 << showSizeof(nulT) <<endl
168 << showSizeof(nulL) <<endl;
169
170 CHECK (sizeof(prep) == sizeof(int)+sizeof(Num<1>)+sizeof(Num<3>)+sizeof(Num<5>));
171 }
172
173
183 void
185 {
186 auto tup = make_tuple (1, 2.3, '4');
187 using Tup = decltype(tup);
188 CHECK (toString(tup) == "«tuple<int, double, char>»──(1,2.3,4)"_expect);
189
190 string dump{};
191 CHECK (dump == "");
192 // apply λ-generic to each element...
193 forEach (tup, [&](auto elm){ dump += "|"+toString(elm); });
194 CHECK (dump == "|1|2.3|4"_expect);
195
196 // apply λ-generic to each element and build new tuple from results
197 auto tupStr = mapEach (tup, [](auto const& elm){ return toString(elm); });
198 CHECK (tupStr == "«tuple<string, string, string>»──(1,2.3,4)"_expect);
199
200 _Fmt showElm{"|%d|▷%s◁"};
201 dump = "";
202 // apply λ-generic with (constexpr) index
203 forEachIDX<Tup> ([&](auto idx)
204 {
205 using Idx = decltype(idx);
206 using Iii = std::integral_constant<size_t, idx.value>;
208 dump += showElm % uint(idx) % get<idx>(tup);
209 });
210 CHECK (dump == "|0|▷1◁|1|▷2.3◁|2|▷4◁"_expect);
211
212
213 // apply λ-generic and combine results
214 auto boolFun = [&](auto idx){ return bool(get<idx>(tup)); };
215
217 get<0>(tup) = 0; // ◁————————————————————— demonstrate that a run-time evaluation happens
220
221 // can use this mechanism also for sole compile-time computation
222 auto integralCheckFun = [](auto idx){ return std::is_integral_v<std::tuple_element_t<idx,Tup>>;};
223
226
227 // Note however, the same can also be achieved simpler,
228 // using any meta-function which takes a single type argument...
229 CHECK (not ElmTypes<Tup>::AndAll<std::is_integral>()); // ... __and_<is_integral<int>,is_integral<double>,is_integral<char>>
231 }
232
233
234
235 template<typename X>
236 string
238 {
239 return lib::test::showType<X>();
240 }
241
242 template<tuple_like X>
243 string
245 {
246 string res{"Tup"};
247 res +="("+toString(std::tuple_size_v<X>)+") : "+ lib::test::showType<X>();
248 lib::meta::forEachIDX<X> ([&](auto i)
249 {
250 using Elm = std::tuple_element_t<i, X>;
251 res += " ▷"+ toString(uint(i)) + ": " + lib::test::showType<Elm>();
252 });
253 return res;
254 }
255
265 void
267 {
268 using Tup = std::tuple<long,short>;
269 using Arr = std::array<int,3>;
270 using Het = lib::HeteroData<int,string>::Chain<short>::ChainExtent<bool,Nil>::ChainType;
271
276
278 // CHECK ( (tuple_element_accessible<Tup,2>));
284
285 // verify the concept detects various tuple-like types
290 CHECK (( tuple_like<std::tuple<int> >));
291 CHECK (( tuple_like<std::tuple<int,char,long> >));
292 CHECK (( tuple_like<std::tuple<> >));
293 CHECK (( tuple_like<std::pair<short,long> >));
294 CHECK (( tuple_like<std::array<short,5> >));
295 CHECK (( tuple_like<std::array<long,0> >));
299
300 // verify arbitrary non-structured types
321
322 // the tuple, the array and the HeteroData are tuple-like,
323 // and will be handled by a special overload, exploiting the additional features
324 CHECK (render<Tup>() == "Tup(2) : tuple<long, short> ▷0: long ▷1: short"_expect);
325 CHECK (render<Arr>() == "Tup(3) : array<int, 3ul> ▷0: int ▷1: int ▷2: int"_expect);
326 CHECK (render<Het>() == "Tup(5) : HeteroData<Node<StorageFrame<0ul, int, string>, "
327 "Node<StorageFrame<1ul, short>, "
328 "Node<StorageFrame<2ul, bool, Nil>, Nil> > > > "
329 "▷0: int ▷1: string ▷2: short ▷3: bool ▷4: Nil"_expect);
330 // the plain type `int` is not tuple-like and thus the fallback case is picked
331 CHECK (render<int>() == "int"_expect);
332
333 CHECK (std::tuple_size_v<const Tup> == 2 );
334
335 using Elm1 = std::tuple_element_t<1, const Tup>;
336 CHECK (lib::test::showType<Elm1>() == "const short"_expect);
337
338 // note: a const tuple will add const qualification to each element type
340 CHECK (lib::test::showType<TupConstSeq>() == "Types<long const, short const>"_expect);
341
342
343 // a unified access function `getElm`
344 // which works both with access by member or free function
345
346 using T1 = decltype(lib::meta::getElm<0> (std::declval<Tup>()));
347 CHECK (lib::test::showType<T1>() == "long &&"_expect);
348
349 using T2 = decltype(lib::meta::getElm<0> (std::declval<Tup&>()));
350 CHECK (lib::test::showType<T2>() == "long&"_expect);
351
352 using T3 = decltype(lib::meta::getElm<0> (std::declval<Tup const&>()));
353 CHECK (lib::test::showType<T3>() == "long const&"_expect);
354
355 using H1 = decltype(lib::meta::getElm<4> (std::declval<Het>()));
356 CHECK (lib::test::showType<H1>() == "Nil"_expect);
357
358 using H2 = decltype(lib::meta::getElm<4> (std::declval<Het&>()));
359 CHECK (lib::test::showType<H2>() == "Nil&"_expect);
360
361 using H3 = decltype(lib::meta::getElm<4> (std::declval<Het const&>()));
362 CHECK (lib::test::showType<H3>() == "Nil const&"_expect);
363 }
364 };
365
366
369
370
371
372}}} // namespace lib::meta::test
A setup with chained data tuples residing in distributed storage.
void check_diagnostics()
verify the test input data
A front-end for using printf-style formatting.
Concept to mark any type compliant to the »tuple protocol«
Helpers typically used while writing tests.
Automatically use custom string conversion in C++ stream output.
Front-end for printf-style string template interpolation.
Maintain a chained sequence of heterogeneous data blocks without allocation.
unsigned int uint
Definition integral.hpp:29
BuildTupleType< TYPES >::Type Tuple
Build a std::tuple from types given as type sequence.
Types< TYPES... >::Seq Seq
enable_if_c< Cond::value, T >::type enable_if
SFINAE helper to control the visibility of specialisations and overloads.
Definition meta/util.hpp:87
constexpr void forEach(TUP &&tuple, FUN fun)
Tuple iteration: perform some arbitrary operation on each element of a tuple.
std::string dump(std::tuple< TYPES... > const &tuple)
convenience function to dump a given tuple's contents.
constexpr auto mapEach(TUP &&tuple, FUN fun)
Apply some arbitrary function onto all elements of a tuple.
Helper: prepend a type to an existing type sequence, thus shifting all elements within the sequence t...
variadic sequence of types
Definition typelist.hpp:102
string showSizeof(size_t siz, string name)
for printing sizeof().
Implementation namespace for support and library code.
Test runner and basic definitions for tests.
std::string toString(TY const &val) noexcept
get some string representation of any object, reliably.
Simplistic test class runner.
#define LAUNCHER(_TEST_CLASS_, _GROUPS_)
Definition run.hpp:116
Variadic type sequence builder.
A collection of frequently used helper functions to support unit testing.
an extension to typelist-diagnostics.hpp, allowing to dump the contents of a Tuple datatype.
Metaprogramming with tuples-of-types and the std::tuple record.
Support for writing metaprogramming unit-tests dealing with typelists and flags.
#define EXPECT(_TY_, RENDERED_STRUCTURE)
#define DISPLAY(_IT_)
#define DUMPVAL(_IT_)