From 8f2f623520b6684a0144fcdf5d465849c2c127cc Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Thu, 5 Apr 2018 12:23:12 +1000 Subject: [PATCH] tuple/value: add zip implementation --- test/tuple.cpp | 13 ++++++++++++ tuple/value.hpp | 53 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/test/tuple.cpp b/test/tuple.cpp index 37cb0134..a2de49c0 100644 --- a/test/tuple.cpp +++ b/test/tuple.cpp @@ -3,6 +3,7 @@ #include "tap.hpp" +#include #include #include @@ -64,5 +65,17 @@ main () tap.expect (std::is_same>::value, "tuple type mapping"); } + + { + std::tuple a (1, 2); + std::array b { 'a', 'b' }; + std::tuple c ( + std::tuple(1, 'a'), + std::tuple(2, 'b') + ); + + tap.expect_eq (c, util::tuple::value::zip (a, b), "tuple zipping"); + } + return tap.status (); } diff --git a/tuple/value.hpp b/tuple/value.hpp index 95454ce6..0d66fbbc 100644 --- a/tuple/value.hpp +++ b/tuple/value.hpp @@ -72,7 +72,58 @@ namespace util::tuple::value { { return detail::map (IndicesV{}, func, arg); } -}; + + + /////////////////////////////////////////////////////////////////////////// + // return a tuple that contains the 'nth' element from each of the supplied + // tuple-like arguments + template + auto + nth (TupleT&&...args) + { + return std::make_tuple ( + std::get (args)... + ); + } + + + /////////////////////////////////////////////////////////////////////////// + namespace detail { + template + auto + zip (std::index_sequence, TupleT &&...args) + { + return std::make_tuple ( + nth (args...)... + ); + } + }; + + + /// converts m arguments of n-tuples into one m-tuple of n-tuples by taking + /// successive elements from each argument tuple. + /// + /// eg, zip (('a', 1.f), (0, nullptr)) becomes (('a', 0), (1.f, nullptr)) + template + auto + zip (Args &&...args) + { + static_assert (sizeof...(args) > 0); + // ensure all the types have the same static size + using all_t = std::tuple...>; + using first_t = std::tuple_element_t<0,all_t>; + + static constexpr auto arity = std::tuple_size_v; + static_assert (( + (arity == std::tuple_size_v>) && ... + )); + + return detail::zip ( + std::make_index_sequence {}, + std::forward (args)... + ); + } +} #endif