Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <cstddef> 7 : #include <tuple> 8 : #include <utility> 9 : 10 : #include "Utilities/Gsl.hpp" 11 : #include "Utilities/TMPL.hpp" 12 : 13 : namespace split_tuple_detail { 14 : template <size_t Offset, size_t... Indices, typename... TupleTypes> 15 : constexpr std::tuple< 16 : std::tuple_element_t<Offset + Indices, std::tuple<TupleTypes...>>...> 17 : extract_subset( 18 : std::index_sequence<Indices...> /*meta*/, 19 : [[maybe_unused]] const gsl::not_null<std::tuple<TupleTypes...>*> tuple) { 20 : return {std::forward< 21 : std::tuple_element_t<Offset + Indices, std::tuple<TupleTypes...>>>( 22 : std::get<Offset + Indices>(*tuple))...}; 23 : } 24 : 25 : template <typename... Offsets, typename... Sizes, typename... TupleTypes> 26 : constexpr auto impl(tmpl::list<Offsets...> /*meta*/, 27 : tmpl::list<Sizes...> /*meta*/, 28 : [[maybe_unused]] std::tuple<TupleTypes...> tuple) { 29 : static_assert((0 + ... + Sizes::value) == sizeof...(TupleTypes), 30 : "Tuple size does not match output sizes."); 31 : return std::make_tuple(extract_subset<Offsets::value>( 32 : std::make_index_sequence<Sizes::value>{}, make_not_null(&tuple))...); 33 : } 34 : } // namespace split_tuple_detail 35 : 36 : /// \ingroup UtilitiesGroup 37 : /// Split a `std::tuple` into multiple tuples 38 : /// 39 : /// \note There are two functions with this name, but doxygen can't 40 : /// figure that out. They have signatures 41 : /// ``` 42 : /// template <typename SizeList, typename... TupleTypes> 43 : /// constexpr auto split_tuple(std::tuple<TupleTypes...> tuple); 44 : /// template <size_t... Sizes, typename... TupleTypes> 45 : /// constexpr auto split_tuple(std::tuple<TupleTypes...> tuple); 46 : /// ``` 47 : /// 48 : /// Given a list of sizes, either directly as template parameters or 49 : /// as a typelist of integral constant types, split the passed tuple 50 : /// into pieces containing the specified number of entries. The 51 : /// passed sizes must sum to the size of the tuple. 52 : /// 53 : /// \returns a `std::tuple` of `std::tuple`s 54 : /// 55 : /// \see std::tuple_cat for the inverse operation. 56 : /// 57 : /// \snippet Utilities/Test_SplitTuple.cpp split_tuple 58 : /// @{ 59 : template <typename SizeList, typename... TupleTypes> 60 1 : constexpr auto split_tuple(std::tuple<TupleTypes...> tuple) { 61 : using offsets = tmpl::pop_back< 62 : tmpl::fold<SizeList, tmpl::list<tmpl::size_t<0>>, 63 : tmpl::bind<tmpl::push_back, tmpl::_state, 64 : tmpl::plus<tmpl::bind<tmpl::back, tmpl::_state>, 65 : tmpl::_element>>>>; 66 : return split_tuple_detail::impl(offsets{}, SizeList{}, std::move(tuple)); 67 : } 68 : 69 : template <size_t... Sizes, typename... TupleTypes> 70 : constexpr auto split_tuple(std::tuple<TupleTypes...> tuple) { 71 : return split_tuple<tmpl::list<tmpl::size_t<Sizes>...>>(std::move(tuple)); 72 : } 73 : /// @}