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 : /// @}
|