TupleLookupByTag_test.cc
Go to the documentation of this file.
1 /**
2  * @file TupleLookupByTag_test.cc
3  * @brief Unit tests on `TupleLookupByTag.h` utilities.
4  * @author Gianluca Petrillo
5  * @date August 17, 2018
6  *
7  * Most of the tests are static and their failure will trigger compilation
8  * errors.
9  */
10 
11 
13 
14 // LArSoft utilities
16 
17 // C/C++ standard libraries
18 #include <tuple>
19 #include <type_traits>
20 #include <memory> // std::addressof()
21 #include <utility> // std::move(), std::forward()
22 #include <cstddef> // std::size_t
23 #include <cassert>
24 
25 
26 //
27 // * in the following tests, static tests that are expected to fail
28 // (with compilation failure) are commented out
29 // * error messages are not very smart; anyway the compiler will report the
30 // line number where the assertion failed
31 //
32 
33 //------------------------------------------------------------------------------
34 //--- Implementation detail tests
35 //------------------------------------------------------------------------------
36 //
37 // test objects preparation
38 //
39 template <typename Tag>
40 struct TestTagged {
41  using myTag = Tag;
42  int value;
43  TestTagged(int value): value(value) {}
44 };
45 struct TestTagA {};
46 struct TestTagB {};
47 struct TestTagC {};
51 
52 using TestTuple_t = std::tuple<int, char, int>;
53 using TestTaggedTuple_t = std::tuple<TestTaggedA, TestTaggedB, TestTaggedA>;
54 
55 template <typename Tagged>
56 struct TestExtractTag { using type = typename Tagged::myTag; };
57 
58 // static_assert(std::is_same<TestExtractTag<int>::type, TestTagA>(), "Bug :-O");
59 static_assert(std::is_same<TestExtractTag<TestTaggedA>::type, TestTagA>(), "Bug :-O");
60 static_assert(std::is_same<TestExtractTag<TestTaggedB>::type, TestTagB>(), "Bug :-O");
61 static_assert(std::is_same<TestExtractTag<TestTaggedC>::type, TestTagC>(), "Bug :-O");
62 
63 //
64 // util::self_type
65 //
66 static_assert( std::is_same<util::self_type<int>::type, int>(), "Bug :'(");
67 static_assert( std::is_same<util::self_type<TestTaggedA>::type, TestTaggedA>(), "Bug :'(");
68 
69 static_assert( std::is_same<util::self_t<int>, int>(), "Bug :'(");
70 static_assert( std::is_same<util::self_t<TestTaggedA>, TestTaggedA>(), "Bug :'(");
71 static_assert(!std::is_same<util::self_t<TestTaggedA>, TestTaggedB>(), "Bug :'(");
72 
73 //
74 // util::typelist_element_type
75 //
76 static_assert( std::is_same<util::typelist_element_type<0U, int, int&, int>::type, int >(), "Bug :O");
77 static_assert( std::is_same<util::typelist_element_type<1U, int, int&, int>::type, int&>(), "Bug :O");
78 static_assert( std::is_same<util::typelist_element_type<2U, int, int&, int>::type, int >(), "Bug :O");
79 // static_assert( std::is_same<util::typelist_element_type<3U, int, int&, int>::type, void>(), "Bug :O");
80 
81 static_assert( std::is_same<util::typelist_element_t<0U, int, int&, int>, int >(), "Bug :O");
82 static_assert( std::is_same<util::typelist_element_t<1U, int, int&, int>, int&>(), "Bug :O");
83 static_assert( std::is_same<util::typelist_element_t<2U, int, int&, int>, int >(), "Bug :O");
84 // static_assert( std::is_same<util::typelist_element_t<3U, int, int&, int>, void>(), "Bug :O");
85 
86 
87 //
88 // util::details::index_of_extracted_type_checked,
89 // util::details::index_of_extracted_type_impl
90 //
94 
96 static_assert(util::details::index_of_extracted_type_impl <util::self_type, int, 2, int, TestTuple_t>() == 2, "Bug :'(");
98 static_assert(util::details::index_of_extracted_type_impl <util::self_type, int, 1, char, TestTuple_t>() == 2, "Bug :'(");
100 static_assert(util::details::index_of_extracted_type_impl <util::self_type, int, 0, int, TestTuple_t>() == 0, "Bug :'(");
102 static_assert(util::details::index_of_extracted_type_impl <util::self_type, TestTaggedA, 2, TestTaggedA, TestTaggedTuple_t>() == 2, "Bug :'(");
104 static_assert(util::details::index_of_extracted_type_impl <util::self_type, TestTaggedA, 1, TestTaggedB, TestTaggedTuple_t>() == 2, "Bug :'(");
106 static_assert(util::details::index_of_extracted_type_impl <util::self_type, TestTaggedA, 0, TestTaggedA, TestTaggedTuple_t>() == 0, "Bug :'(");
108 static_assert(util::details::index_of_extracted_type_impl <TestExtractTag, TestTagA, 2, TestTagA, TestTaggedTuple_t>() == 2, "Bug :'(");
110 static_assert(util::details::index_of_extracted_type_impl <TestExtractTag, TestTagA, 1, TestTagB, TestTaggedTuple_t>() == 2, "Bug :'(");
112 static_assert(util::details::index_of_extracted_type_impl <TestExtractTag, TestTagA, 0, TestTagA, TestTaggedTuple_t>() == 0, "Bug :'(");
113 
114 //
115 // util::details::index_of_extracted_type_checked_after
116 //
129 
130 //
131 // util::details::index_of_type_base
132 //
142 
143 //
144 // util::details::index_of_type_helper
145 //
146 // static_assert(util::details::index_of_type_helper<util::self_type, int, TestTuple_t >::value == 0, "Bug :'(");
148 // static_assert(util::details::index_of_type_helper<util::self_type, void, TestTuple_t >::value == 3, "Bug :'(");
149 // static_assert(util::details::index_of_type_helper<util::self_type, TestTaggedA, TestTaggedTuple_t>::value == 0, "Bug :'(");
151 // static_assert(util::details::index_of_type_helper<util::self_type, TestTaggedC, TestTaggedTuple_t>::value == 3, "Bug :'(");
152 // static_assert(util::details::index_of_type_helper<TestExtractTag, TestTagA, TestTaggedTuple_t>::value == 0, "Bug :'(");
154 // static_assert(util::details::index_of_type_helper<TestExtractTag, TestTagC, TestTaggedTuple_t>::value == 3, "Bug :'(");
155 
156 
157 //
158 // util::index_of_extracted_type
159 //
160 // static_assert(util::index_of_extracted_type<util::self_type, int, TestTuple_t >() == 0, "Bug :'(");
162 // static_assert(util::index_of_extracted_type<util::self_type, void, TestTuple_t >() == 3, "Bug :'(");
163 // static_assert(util::index_of_extracted_type<util::self_type, TestTaggedA, TestTaggedTuple_t>() == 0, "Bug :'(");
165 // static_assert(util::index_of_extracted_type<util::self_type, TestTaggedC, TestTaggedTuple_t>() == 3, "Bug :'(");
166 // static_assert(util::index_of_extracted_type<TestExtractTag, TestTagA, TestTaggedTuple_t>() == 0, "Bug :'(");
168 // static_assert(util::index_of_extracted_type<TestExtractTag, TestTagC, TestTaggedTuple_t>() == 3, "Bug :'(");
169 
170 
171 //
172 // util::index_of_type
173 //
174 // static_assert(util::index_of_type<int, TestTuple_t >() == 0, "Bug :'(");
175  static_assert(util::index_of_type<char, TestTuple_t >() == 1, "Bug :'(");
176 // static_assert(util::index_of_type<void, TestTuple_t >() == 3, "Bug :'(");
177 // static_assert(util::index_of_type<TestTaggedA, TestTaggedTuple_t>() == 0, "Bug :'(");
178  static_assert(util::index_of_type<TestTaggedB, TestTaggedTuple_t>() == 1, "Bug :'(");
179 // static_assert(util::index_of_type<TestTaggedC, TestTaggedTuple_t>() == 3, "Bug :'(");
180 
181 
182 //
183 // util::has_extracted_type
184 //
194 
195 //
196 // util::has_type
197 //
198 static_assert( util::has_type<int , TestTuple_t >(), "Bug :'(");
199 static_assert( util::has_type<char, TestTuple_t >(), "Bug :'(");
200 static_assert(!util::has_type<void, TestTuple_t >(), "Bug :'(");
201 static_assert( util::has_type<TestTaggedA, TestTaggedTuple_t>(), "Bug :'(");
202 static_assert( util::has_type<TestTaggedB, TestTaggedTuple_t>(), "Bug :'(");
203 static_assert(!util::has_type<TestTaggedC, TestTaggedTuple_t>(), "Bug :'(");
204 
205 //
206 // util::type_is_in
207 //
208 static_assert( util::type_is_in<int, int, char, int>(), "Buuug.");
209 static_assert( util::type_is_in<char, int, char, int>(), "Buuug.");
210 static_assert(!util::type_is_in<void, int, char, int>(), "Buuug.");
211 
212 //
213 // util::details::count_type_in_list
214 //
215 static_assert(util::count_type_in_list<int, int, char, int>() == 2, "Buuug.");
216 static_assert(util::count_type_in_list<char, int, char, int>() == 1, "Buuug.");
217 static_assert(util::count_type_in_list<void, int, char, int>() == 0, "Buuug.");
218 
219 //
220 // util::details::count_type_in_tuple
221 //
222 static_assert(util::count_type_in_tuple<int, std::tuple<int, char, int>>() == 2, "Buuug.");
223 static_assert(util::count_type_in_tuple<char, std::tuple<int, char, int>>() == 1, "Buuug.");
224 static_assert(util::count_type_in_tuple<void, std::tuple<int, char, int>>() == 0, "Buuug.");
225 
226 //
227 // util::has_duplicate_types_impl
228 //
229 static_assert( util::details::has_duplicate_types_impl<std::tuple<int, char, int>, int, char, void>(), "Buuug.");
230 static_assert( util::details::has_duplicate_types_impl<std::tuple<int, char, int>, int, char >(), "Buuug.");
231 static_assert( util::details::has_duplicate_types_impl<std::tuple<int, char, int>, int , void>(), "Buuug.");
232 static_assert( util::details::has_duplicate_types_impl<std::tuple<int, char, int>, int, char, void>(), "Buuug.");
233 static_assert(!util::details::has_duplicate_types_impl<std::tuple<int, char, int> , char, void>(), "Buuug.");
234 static_assert( util::details::has_duplicate_types_impl<std::tuple<int, char, int>, int >(), "Buuug.");
235 static_assert(!util::details::has_duplicate_types_impl<std::tuple<int, char, int> , char >(), "Buuug.");
236 static_assert(!util::details::has_duplicate_types_impl<std::tuple<int, char, int> , void>(), "Buuug.");
237 
238 //
239 // util::has_duplicate_types
240 //
241 static_assert( util::has_duplicate_types<std::tuple<int, char, int >>(), "Buuug.");
242 static_assert(!util::has_duplicate_types<std::tuple<int, char, long>>(), "Buuug.");
243 
244 //
245 // util::details::count_tags_in_list
246 //
250 
251 //
252 // util::count_extracted_types
253 //
263 
264 //
265 // util::count_types
266 //
267 static_assert(util::count_types<int , TestTuple_t >() == 2, "Bug :'(");
268 static_assert(util::count_types<char, TestTuple_t >() == 1, "Bug :'(");
269 static_assert(util::count_types<void, TestTuple_t >() == 0, "Bug :'(");
270 static_assert(util::count_types<TestTaggedA, TestTaggedTuple_t>() == 2, "Bug :'(");
271 static_assert(util::count_types<TestTaggedB, TestTaggedTuple_t>() == 1, "Bug :'(");
272 static_assert(util::count_types<TestTaggedC, TestTaggedTuple_t>() == 0, "Bug :'(");
273 
274 
275 namespace my {
276 
277  // A class supporting tuple-type operations.
278  template <typename... Data>
279  class MyTuple {
280  using tuple_t = std::tuple<Data...>;
282 
283 
284  public:
285  template <std::size_t I>
286  using element_type = std::tuple_element_t<I, tuple_t>;
287 
288  MyTuple(Data&&... data): data(std::forward<Data>(data)...) {}
289  MyTuple(tuple_t&& data): data(std::move(data)) {}
290 
291  template <std::size_t I>
292  auto get() -> decltype(auto) { return std::get<I>(data); }
293 
294  template <std::size_t I>
295  auto get() const -> decltype(auto) { return std::get<I>(data); }
296 
297  template <typename T>
298  auto get() -> decltype(auto) { return std::get<T>(data); }
299 
300  template <typename T>
301  auto get() const -> decltype(auto) { return std::get<T>(data); }
302 
303 
304  static constexpr std::size_t tuple_size()
305  { return std::tuple_size<tuple_t>(); }
306 
307  }; // MyTuple
308 
309 
310  template <typename... Data>
311  auto make_my_tuple(Data&&... data)
312  { return MyTuple<Data...>{ std::forward<Data>(data)... }; }
313 
314 
315  template <std::size_t I, typename... T>
316  auto get(MyTuple<T...> const& t) -> decltype(auto)
317  { return t.template get<I>(); }
318 
319  template <typename Target, typename... T>
320  auto get(MyTuple<T...> const& t) -> decltype(auto)
321  { return t.template get<Target>(); }
322 
323 
324 } // namespace my
325 
326 
327 namespace std {
328  // specialization of tuple-like operations for the new type
329 
330  template <std::size_t I, typename... T>
331  class tuple_element<I, my::MyTuple<T...>> {
332  public:
333  using type = typename my::MyTuple<T...>::template element_type<I>;
334  }; // class tuple_element<MyTuple>
335 
336  template <typename... T>
337  class tuple_size<my::MyTuple<T...>>
338  : public std::integral_constant<std::size_t, my::MyTuple<T...>::tuple_size()>
339  {};
340 
341 } // namespace std
342 
343 
344 //
345 // test types using the custom tuple
346 //
347 template <typename Tag, typename Payload = void>
348 struct TaggedType: public TaggedType<Tag> {
349  Payload data;
350 
351  TaggedType(Payload data): data(data) {}
352 }; // TaggedType
353 
354 template <typename Tag>
355 struct TaggedType <Tag, void> {
356  using tag = Tag;
357 };
358 
362 
363 
365 
366  struct MyData {
367  int content = 5;
368  };
369 
370  struct MyStonedData: public MyData, public lar::UncopiableAndUnmovableClass {};
371 
372  MyData lightData; // moveable, copiable
373  MyStonedData heavyStone; // unmoveable, uncopiable
374 
375  decltype(auto) lightDataTagged = util::makeTagged<TagA>(lightData );
376  decltype(auto) heavyStoneTagged = util::makeTagged<TagA>(heavyStone );
377  decltype(auto) lightDataCopyTagged = util::makeTagged<TagA>(MyData(lightData));
378 
379  static_assert( std::is_lvalue_reference<decltype(util::makeTagged<TagA>(lightData) )>(), "makeTagged(moveable lvalue) does not produce a reference");
380  static_assert( std::is_lvalue_reference<decltype(util::makeTagged<TagA>(heavyStone) )>(), "makeTagged(unmoveable lvalue) does not produce a reference");
381  static_assert(!std::is_lvalue_reference<decltype(util::makeTagged<TagA>(MyData(lightData)))>(), "makeTagged(rvalue) produces a (lvalue) reference" );
382  static_assert(!std::is_rvalue_reference<decltype(util::makeTagged<TagA>(MyData(lightData)))>(), "makeTagged(rvalue) produces a (rvalue) reference" );
383 
384  assert(std::addressof(lightDataTagged ) == std::addressof(lightData ));
385  assert(std::addressof(heavyStoneTagged ) == std::addressof(heavyStone));
386  assert(std::addressof(lightDataCopyTagged) != std::addressof(lightData ));
387 
388 } // testMakeTagged()
389 
390 
391 int main() {
392 
393  //
394  // test data
395  //
396  auto const testTuple = std::make_tuple<TestTaggedA, TestTaggedB, TestTaggedA>( 1, 2, 3 );
397  assert((std::get<0>(testTuple).value == 1));
398  assert((std::get<1>(testTuple).value == 2));
399  assert((std::get<2>(testTuple).value == 3));
400  using std::get;
401 // static_assert((index_of_extracted_type<TestExtractTag, TestTagA, TestTaggedTuple_t>(testTuple)>::value == 0), "Bug!");
403  assert(get<1U>(testTuple).value == 2);
405 // assert((util::getByExtractedType<TestExtractTag, TestTagA>(testTuple).value == 1));
406  assert((util::getByExtractedType<TestExtractTag, TestTagB>(testTuple).value == 2));
407 // assert((util::getByExtractedType<TestExtractTag, TestTagC>(testTuple).value == 3));
408 
409  using DataA = TaggedType<TagA, int>;
410  using DataB = TaggedType<TagB, int>;
411  using DataC = TaggedType<TagC, char>;
412 
413  auto data = my::make_my_tuple<DataA, DataC, DataB>(64, 'b', 66);
414  auto dataWithDupl = my::make_my_tuple<DataA, DataC, DataA>(64, 'b', 66);
415 
416  //
417  // traditional std::get()
418  //
419  using std::get;
420  static_assert(std::is_same<std::decay_t<decltype(get<0U>(data ))>, DataA>(), "Unexpected type 1");
421  static_assert(std::is_same<std::decay_t<decltype(get<1U>(data ))>, DataC>(), "Unexpected type 2");
422  static_assert(std::is_same<std::decay_t<decltype(get<2U>(data ))>, DataB>(), "Unexpected type 3");
423  static_assert(std::is_same<std::decay_t<decltype(get<0U>(dataWithDupl))>, DataA>(), "Unexpected type 1 (dupl)");
424  static_assert(std::is_same<std::decay_t<decltype(get<1U>(dataWithDupl))>, DataC>(), "Unexpected type 2 (dupl)");
425  static_assert(std::is_same<std::decay_t<decltype(get<2U>(dataWithDupl))>, DataA>(), "Unexpected type 3 (dupl)");
426 
427  //
428  // traditional std::get() (by type)
429  //
430  using std::get;
431  static_assert(std::is_same<std::decay_t<decltype(get<DataA>(data))>, DataA>(), "Unexpected type 1" );
432  static_assert(std::is_same<std::decay_t<decltype(get<DataC>(data))>, DataC>(), "Unexpected type 2" );
433  static_assert(std::is_same<std::decay_t<decltype(get<DataB>(data))>, DataB>(), "Unexpected type 3" );
434 // static_assert(std::is_same<std::decay_t<decltype(get<DataA>(dataWithDupl))>, DataA>(), "Unexpected type 1 (dupl)"); // does not compile: duplicate types!
435  static_assert(std::is_same<std::decay_t<decltype(get<DataC>(dataWithDupl))>, DataC>(), "Unexpected type 2 (dupl)");
436 // static_assert(std::is_same<std::decay_t<decltype(get<DataA>(dataWithDupl))>, DataA>(), "Unexpected type 3 (dupl)"); // does not compile: duplicate types!
437 
438  //
439  // traditional std::tuple_element()
440  //
441  using std::get;
442  static_assert(std::is_same<std::tuple_element_t<0U, decltype(data )>, DataA>(), "Unexpected type 1");
443  static_assert(std::is_same<std::tuple_element_t<1U, decltype(data )>, DataC>(), "Unexpected type 2");
444  static_assert(std::is_same<std::tuple_element_t<2U, decltype(data )>, DataB>(), "Unexpected type 3");
445  static_assert(std::is_same<std::tuple_element_t<0U, decltype(dataWithDupl)>, DataA>(), "Unexpected type 1 (dupl)");
446  static_assert(std::is_same<std::tuple_element_t<1U, decltype(dataWithDupl)>, DataC>(), "Unexpected type 2 (dupl)");
447  static_assert(std::is_same<std::tuple_element_t<2U, decltype(dataWithDupl)>, DataA>(), "Unexpected type 3 (dupl)");
448 
449  //
450  // traditional std::tuple_size
451  //
452  static_assert(std::tuple_size<decltype(data )>() == 3U, "Unexpected tuple size");
453  static_assert(std::tuple_size<decltype(dataWithDupl)>() == 3U, "Unexpected tuple size (dupl)");
454 
455 
456  //
457  // util::index_of_type()
458  //
459  static_assert(util::index_of_type<DataA, decltype(data) >() == 0U, "Unexpected type 1");
460  static_assert(util::index_of_type<DataC, decltype(data) >() == 1U, "Unexpected type 2");
461  static_assert(util::index_of_type<DataB, decltype(data) >() == 2U, "Unexpected type 3");
462 // static_assert(util::index_of_type<DataA, decltype(dataWithDupl)>() == 0U, "Unexpected type 1 (dupl)");
463  static_assert(util::index_of_type<DataC, decltype(dataWithDupl)>() == 1U, "Unexpected type 2 (dupl)");
464 // static_assert(util::index_of_type<DataA, decltype(dataWithDupl)>() == 2U, "Unexpected type 3 (dupl)");
465 
466  //
467  // util::index_of_tag()
468  //
469  static_assert(util::index_of_tag<TagA, decltype(data) >() == 0U, "Unexpected tagged type 1");
470  static_assert(util::index_of_tag<TagC, decltype(data) >() == 1U, "Unexpected tagged type 2");
471  static_assert(util::index_of_tag<TagB, decltype(data) >() == 2U, "Unexpected tagged type 3");
472 // static_assert(util::index_of_tag<TagA, decltype(dataWithDupl)>() == 0U, "Unexpected tagged type 1 (dupl)");
473  static_assert(util::index_of_tag<TagC, decltype(dataWithDupl)>() == 1U, "Unexpected tagged type 2 (dupl)");
474 // static_assert(util::index_of_tag<TagA, decltype(dataWithDupl)>() == 2U, "Unexpected tagged type 3 (dupl)");
475 
476  //
477  // util::type_with_tag()
478  //
479  static_assert(std::is_same<util::type_with_tag_t<TagA, decltype(data) >, DataA>(), "Unexpected tagged type 1");
480  static_assert(std::is_same<util::type_with_tag_t<TagC, decltype(data) >, DataC>(), "Unexpected tagged type 2");
481  static_assert(std::is_same<util::type_with_tag_t<TagB, decltype(data) >, DataB>(), "Unexpected tagged type 3");
482 // static_assert(std::is_same<util::type_with_tag_t<TagA, decltype(dataWithDupl)>, DataA>(), "Unexpected tagged type 1 (dupl)");
483  static_assert(std::is_same<util::type_with_tag_t<TagC, decltype(dataWithDupl)>, DataC>(), "Unexpected tagged type 2 (dupl)");
484 // static_assert(std::is_same<util::type_with_tag_t<TagA, decltype(dataWithDupl)>, DataA>(), "Unexpected tagged type 3 (dupl)");
485 
486  //
487  // util::has_type()
488  //
489  static_assert( util::has_type<DataA, decltype(data) >(), "Unexpected type 1");
490  static_assert( util::has_type<DataC, decltype(data) >(), "Unexpected type 2");
491  static_assert( util::has_type<DataB, decltype(data) >(), "Unexpected type 3");
492  static_assert( util::has_type<DataA, decltype(dataWithDupl)>(), "Unexpected type 1 (dupl)");
493  static_assert( util::has_type<DataC, decltype(dataWithDupl)>(), "Unexpected type 2 (dupl)");
494  static_assert(!util::has_type<DataB, decltype(dataWithDupl)>(), "Unexpected type 3 (dupl)");
495 
496  //
497  // util::has_tag()
498  //
499  static_assert( util::has_tag<TagA, decltype(data) >(), "Unexpected tagged type 1");
500  static_assert( util::has_tag<TagC, decltype(data) >(), "Unexpected tagged type 2");
501  static_assert( util::has_tag<TagB, decltype(data) >(), "Unexpected tagged type 3");
502  static_assert( util::has_tag<TagA, decltype(dataWithDupl)>(), "Unexpected tagged type 1 (dupl)");
503  static_assert( util::has_tag<TagC, decltype(dataWithDupl)>(), "Unexpected tagged type 2 (dupl)");
504  static_assert(!util::has_tag<TagB, decltype(dataWithDupl)>(), "Unexpected tagged type 3 (dupl)");
505 
506  //
507  // util::count_types()
508  //
509  static_assert(util::count_types<DataA, decltype(data) >() == 1, "Unexpected type 1");
510  static_assert(util::count_types<DataC, decltype(data) >() == 1, "Unexpected type 2");
511  static_assert(util::count_types<DataB, decltype(data) >() == 1, "Unexpected type 3");
512  static_assert(util::count_types<DataA, decltype(dataWithDupl)>() == 2, "Unexpected type 1 (dupl)");
513  static_assert(util::count_types<DataC, decltype(dataWithDupl)>() == 1, "Unexpected type 2 (dupl)");
514  static_assert(util::count_types<DataB, decltype(dataWithDupl)>() == 0, "Unexpected type 3 (dupl)");
515 
516  //
517  // util::count_tags()
518  //
519  static_assert(util::count_tags<TagA, decltype(data) >() == 1, "Unexpected type 1");
520  static_assert(util::count_tags<TagC, decltype(data) >() == 1, "Unexpected type 2");
521  static_assert(util::count_tags<TagB, decltype(data) >() == 1, "Unexpected type 3");
522  static_assert(util::count_tags<TagA, decltype(dataWithDupl)>() == 2, "Unexpected type 1 (dupl)");
523  static_assert(util::count_tags<TagC, decltype(dataWithDupl)>() == 1, "Unexpected type 2 (dupl)");
524  static_assert(util::count_tags<TagB, decltype(dataWithDupl)>() == 0, "Unexpected type 3 (dupl)");
525 
526  //
527  // util::has_duplicate_types()
528  //
529  static_assert(!util::has_duplicate_types<decltype(data) >(), "Type has duplicate tags!");
530  static_assert( util::has_duplicate_types<decltype(dataWithDupl)>(), "Type has no duplicate tags");
531 
532  //
533  // util::has_duplicate_tags()
534  //
535  static_assert(!util::has_duplicate_tags<decltype(data) >(), "Type has duplicate tags!");
536  static_assert( util::has_duplicate_tags<decltype(dataWithDupl)>(), "Type has no duplicate tags");
537 
538  //
539  // util::getByTag()
540  //
541  static_assert(std::is_same<std::decay_t<decltype(util::getByTag<TagA>(data) .data)>, int >(), "Unexpected type 1" );
542  static_assert(std::is_same<std::decay_t<decltype(util::getByTag<TagC>(data) .data)>, char>(), "Unexpected type 2" );
543  static_assert(std::is_same<std::decay_t<decltype(util::getByTag<TagB>(data) .data)>, int >(), "Unexpected type 3" );
544 // static_assert(std::is_same<std::decay_t<decltype(util::getByTag<TagA>(dataWithDupl).data)>, int >(), "Unexpected type 1 (dupl)"); // does not compile: duplicate types!
545  static_assert(std::is_same<std::decay_t<decltype(util::getByTag<TagC>(dataWithDupl).data)>, char>(), "Unexpected type 2 (dupl)");
546 // static_assert(std::is_same<std::decay_t<decltype(util::getByTag<TagA>(dataWithDupl).data)>, int >(), "Unexpected type 3 (dupl)"); // does not compile: duplicate types!
547 
548  assert((util::getByTag<TagA>(data) ).data == 64);
549  assert((util::getByTag<TagC>(data) ).data == 'b');
550  assert((util::getByTag<TagB>(data) ).data == 66);
551 // assert((util::getByTag<TagA>(dataWithDupl)).data == 64); // does not compile: duplicate types!
552  assert((util::getByTag<TagC>(dataWithDupl)).data == 'b');
553 // assert((util::getByTag<TagA>(dataWithDupl)).data == 66); // does not compile: duplicate types!
554 
555  //
556  // makeTagged()
557  //
558  testMakeTagged();
559 
560  return 0;
561 } // main()
An empty class that can&#39;t be copied nor moved.
Counts the elements of a tuple-like type containing a Target type.
auto make_my_tuple(Data &&...data)
Defines classes that can&#39;t be copied nor moved.
Definition: tag.cpp:4
std::tuple< int, char, int > TestTuple_t
STL namespace.
TaggedType(Payload data)
Holds whether the Target type is element of the specified std::tuple.
Tag class parametrized by a sequence of numbers.
typename self_type< T >::type self_t
The very same type as in the template argument.
Definition: MetaUtils.h:68
MyTuple(Data &&...data)
std::tuple_element< N, std::tuple< T... >> typelist_element_type
Returns the N type of the type list.
auto get(MyTuple< T... > const &t) -> decltype(auto)
static constexpr std::size_t tuple_size()
typename tuple_element< I, Node >::type tuple_element_t
Definition: AssnsNode.h:56
def move(depos, offset)
Definition: depos.py:107
std::tuple< TestTaggedA, TestTaggedB, TestTaggedA > TestTaggedTuple_t
TestTagged(int value)
typename typelist_element_type< N, T... >::type typelist_element_t
Direct access to the value in typelist_element_type.
void testMakeTagged()
Trait holding whether an element in Tuple type contains Target.
Traits holding whether elements of Tuple have duplicate types.
Returns the index of the element in Tuple with the specified type.
MyTuple(tuple_t &&data)
typename type_with_tag< Tag, Tuple >::type type_with_tag_t
Direct access to the value in type_with_tag.
Utilities to address elements of a tuple-like class by tag.
std::tuple< Data... > tuple_t
std::tuple_element_t< I, tuple_t > element_type
typename Tagged::myTag type
int main()