/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright 2015-2018 Danny Robson */ #pragma once #include "index.hpp" #include "../types.hpp" #include #include #include #include namespace cruft::tuple::value { namespace detail { // Call the function for the value at the index `S`, then increment // the index and call ourselves again if we haven't reached the end. // // A detail function is used to simplify the case for empty tuples; // ie, we'd like to keep the index assertion, but a constexpr-if won't // elide the assertion. template< typename FunctionT, typename TupleT, std::size_t S = 0 > void each (FunctionT &&func, TupleT &&value) { using tuple_t = std::decay_t; static_assert (S < std::tuple_size_v); std::invoke (func, std::get (value)); if constexpr (S + 1 < std::tuple_size_v) { each ( std::forward (func), std::forward (value) ); } } } /////////////////////////////////////////////////////////////////////////// /// Call a provided functor of type FunctionT with each value in a /// provided tuple-like object TupleT template< typename FunctionT, typename TupleT > void each (FunctionT &&func, TupleT &&value) { if constexpr (std::tuple_size_v> > 0) { return detail::each ( std::forward (func), std::forward (value) ); } } /////////////////////////////////////////////////////////////////////////// namespace detail { template auto map (std::index_sequence, FuncT &&func, ArgT &&arg) { return std::tuple ( std::invoke (func, std::get (arg))... ); } }; /// returns a tuple of the result of applying the provided function to /// each value of the supplied tuple. template < typename FuncT, typename ArgT, typename IndicesV = std::make_index_sequence< std::tuple_size_v> > > auto map (FuncT &&func, ArgT &&arg) { return detail::map ( IndicesV{}, std::forward (func), std::forward (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)... ); } /////////////////////////////////////////////////////////////////////////// namespace detail { template auto reverse (index::indices, TupleT &&val) { return std::make_tuple ( std::get (val)... ); } }; //------------------------------------------------------------------------- template auto reverse (TupleT &&val) { return detail::reverse ( index::make_reverse_t< std::tuple_size_v> > {}, std::forward (val) ); } }