tuple/value: add zip implementation

This commit is contained in:
Danny Robson 2018-04-05 12:23:12 +10:00
parent 5c2b52b30b
commit 8f2f623520
2 changed files with 65 additions and 1 deletions

View File

@ -3,6 +3,7 @@
#include "tap.hpp"
#include <array>
#include <typeindex>
#include <vector>
@ -64,5 +65,17 @@ main ()
tap.expect (std::is_same<dst_t, std::tuple<int>>::value, "tuple type mapping");
}
{
std::tuple a (1, 2);
std::array<char,2> 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 ();
}

View File

@ -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 <size_t N, typename ...TupleT>
auto
nth (TupleT&&...args)
{
return std::make_tuple (
std::get<N> (args)...
);
}
///////////////////////////////////////////////////////////////////////////
namespace detail {
template <typename ...TupleT, size_t ...Elements>
auto
zip (std::index_sequence<Elements...>, TupleT &&...args)
{
return std::make_tuple (
nth<Elements> (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 <typename ...Args >
auto
zip (Args &&...args)
{
static_assert (sizeof...(args) > 0);
// ensure all the types have the same static size
using all_t = std::tuple<std::decay_t<Args>...>;
using first_t = std::tuple_element_t<0,all_t>;
static constexpr auto arity = std::tuple_size_v<first_t>;
static_assert ((
(arity == std::tuple_size_v<std::decay_t<Args>>) && ...
));
return detail::zip (
std::make_index_sequence<arity> {},
std::forward<Args> (args)...
);
}
}
#endif