19 #include <type_traits> 39 template <
typename Tag>
55 template <
typename Tagged>
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 :'(");
278 template <
typename...
Data>
285 template <std::
size_t I>
291 template <std::
size_t I>
292 auto get() -> decltype(
auto) {
return std::get<I>(
data); }
294 template <std::
size_t I>
295 auto get()
const -> decltype(
auto) {
return std::get<I>(
data); }
297 template <
typename T>
298 auto get() -> decltype(
auto) {
return std::get<T>(
data); }
300 template <
typename T>
301 auto get()
const -> decltype(
auto) {
return std::get<T>(
data); }
305 {
return std::tuple_size<tuple_t>(); }
310 template <
typename...
Data>
315 template <std::size_t
I,
typename...
T>
317 {
return t.template get<I>(); }
319 template <
typename Target,
typename...
T>
320 auto get(
MyTuple<
T...>
const&
t) -> decltype(
auto)
321 {
return t.template get<Target>(); }
330 template <std::size_t
I,
typename...
T>
331 class tuple_element<I,
my::MyTuple<T...>> {
336 template <
typename...
T>
337 class tuple_size<
my::MyTuple<T...>>
338 :
public std::integral_constant<std::size_t, my::MyTuple<T...>::tuple_size()>
347 template <
typename Tag,
typename Payload =
void>
354 template <
typename Tag>
373 MyStonedData heavyStone;
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));
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" );
384 assert(std::addressof(lightDataTagged ) == std::addressof(lightData ));
385 assert(std::addressof(heavyStoneTagged ) == std::addressof(heavyStone));
386 assert(std::addressof(lightDataCopyTagged) != std::addressof(lightData ));
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));
403 assert(get<1U>(testTuple).
value == 2);
406 assert((util::getByExtractedType<TestExtractTag, TestTagB>(testTuple).value == 2));
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);
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)");
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" );
435 static_assert(std::is_same<std::decay_t<decltype(get<DataC>(dataWithDupl))>, DataC>(),
"Unexpected type 2 (dupl)");
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)");
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)");
463 static_assert(
util::index_of_type<DataC, decltype(dataWithDupl)>() == 1U,
"Unexpected type 2 (dupl)");
473 static_assert(
util::index_of_tag<
TagC, decltype(dataWithDupl)>() == 1U,
"Unexpected tagged type 2 (dupl)");
483 static_assert(std::is_same<
util::type_with_tag_t<
TagC, decltype(dataWithDupl)>, DataC>(),
"Unexpected tagged type 2 (dupl)");
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)");
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)");
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)");
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)");
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" );
545 static_assert(std::is_same<std::decay_t<decltype(util::getByTag<TagC>(dataWithDupl).data)>,
char>(),
"Unexpected type 2 (dupl)");
548 assert((util::getByTag<TagA>(data) ).data == 64);
549 assert((util::getByTag<TagC>(data) ).data ==
'b');
550 assert((util::getByTag<TagB>(data) ).data == 66);
552 assert((util::getByTag<TagC>(dataWithDupl)).data ==
'b');
An empty class that can't be copied nor moved.
auto make_my_tuple(Data &&...data)
Defines classes that can't be copied nor moved.
std::tuple< int, char, int > TestTuple_t
Holds whether the Target type is element of the specified std::tuple.
Tag class parametrized by a sequence of numbers.
auto get(MyTuple< T... > const &t) -> decltype(auto)
static constexpr std::size_t tuple_size()
typename tuple_element< I, Node >::type tuple_element_t
std::tuple< TestTaggedA, TestTaggedB, TestTaggedA > TestTaggedTuple_t
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