/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright 2015-2018 Danny Robson */ #ifndef CRUFT_UTIL_TUPLE_VALUE_HPP #define CRUFT_UTIL_TUPLE_VALUE_HPP #include "index.hpp" #include "../types.hpp" #include #include #include #include namespace util::tuple::value { /////////////////////////////////////////////////////////////////////////// /// Call a provided functor of type FunctionT with each value in a /// provided tuple-like object TupleT 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)); } } /////////////////////////////////////////////////////////////////////////// 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{}, 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)... ); } /////////////////////////////////////////////////////////////////////////// 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) ); } } #endif