/* * 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 2018 Danny Robson <danny@nerdcruft.net> */ #ifndef CRUFT_UTIL_TUPLE_INDEX_HPP #define CRUFT_UTIL_TUPLE_INDEX_HPP #include <cstddef> /////////////////////////////////////////////////////////////////////////// // the implementation of all the below must be standalone as they are a // potential building block in other algorithms and we can't be sure we // won't create a dependency loop somewhere. namespace cruft::tuple::index { /////////////////////////////////////////////////////////////////////////// template <size_t ...Indices> struct indices {}; /////////////////////////////////////////////////////////////////////////// template <typename A, typename B> struct cat; //------------------------------------------------------------------------- template < size_t ...A, size_t ...B > struct cat< indices<A...>, indices<B...> > { using type = indices<A..., B...>; }; //------------------------------------------------------------------------- template <typename A, typename B> using cat_t = typename cat<A,B>::type; /////////////////////////////////////////////////////////////////////////// namespace detail { template <size_t N> struct make_indices { using type = cat_t< typename make_indices<N-1>::type, indices<N-1> >; }; template <> struct make_indices<0> { using type = indices<>; }; }; //------------------------------------------------------------------------- // create a monotonically increasing index sequence over the range [0,N) template <size_t N> struct make_indices { using type = typename detail::make_indices<N>::type; }; //------------------------------------------------------------------------- template <size_t N> using make_indices_t = typename make_indices<N>::type; /////////////////////////////////////////////////////////////////////////// namespace detail { template <typename Indices> struct make_reverse; template <size_t Head, size_t ...Tail> struct make_reverse< indices<Head,Tail...> > { using type = cat_t< typename make_reverse<indices<Tail...>>::type, indices<Head> >; }; template <> struct make_reverse< indices<> > { using type = indices<>; }; }; //------------------------------------------------------------------------- // create a montonically decreasing index sequence over the range (N-1, 0]. // // eg, make_reverse<3> is indices<3,2,1,0> template <size_t N> struct make_reverse { using type = typename detail::make_reverse< make_indices_t<N> >::type; }; //------------------------------------------------------------------------- template <size_t N> using make_reverse_t = typename make_reverse<N>::type; }; #endif