6
6
#ifndef LTPL_LTPL_TUPLE_HPP
7
7
#define LTPL_LTPL_TUPLE_HPP
8
8
9
+ #include < array>
9
10
#include < cstddef>
10
11
#include < type_traits>
11
12
#include < utility>
@@ -17,6 +18,9 @@ class Tuple;
17
18
18
19
namespace detail
19
20
{
21
+ template <class ... T>
22
+ struct TypeList ;
23
+
20
24
// A type that can be constructed from anything, useful for extracting the nth-element of a type list later.
21
25
template <std::size_t >
22
26
struct Anything
@@ -200,14 +204,23 @@ template <std::size_t... Ns>
200
204
struct GetNth
201
205
{
202
206
template <class Nth >
203
- constexpr Nth& operator ()(Anything<Ns>..., Nth& nth, auto &...) noexcept
207
+ constexpr Nth&& operator ()(Anything<Ns>..., Nth&& nth, auto & &...) noexcept
204
208
{
205
- return nth;
209
+ return static_cast <Nth&&>( nth) ;
206
210
}
207
211
};
208
212
209
213
// An implementation of nth-element similar to the `Concept expansion` described by Kris Jusiak in his talk `The Nth
210
214
// Element: A Case Study - CppNow 2022` but compatible with every C++20 compiler and easily backportable to C++14.
215
+ template <std::size_t I, class ... T>
216
+ constexpr decltype (auto ) get_nth(T&&... t) noexcept
217
+ {
218
+ return [&]<std::size_t ... Ns>(std::index_sequence<Ns...>) -> decltype (auto )
219
+ {
220
+ return GetNth<Ns...>{}(static_cast <T&&>(t)...);
221
+ }(std::make_index_sequence<I>{});
222
+ }
223
+
211
224
template <std::size_t I, class ... T>
212
225
constexpr decltype (auto ) get(ltpl::Tuple<T...>& tuple) noexcept
213
226
{
@@ -231,6 +244,12 @@ constexpr bool all_true(bool const (&array)[N]) noexcept
231
244
}
232
245
return true ;
233
246
}
247
+
248
+ struct TupleCatIndex
249
+ {
250
+ std::size_t outer;
251
+ std::size_t inner;
252
+ };
234
253
} // namespace detail
235
254
236
255
template <class ... T>
@@ -460,6 +479,34 @@ template <class... T>
460
479
{
461
480
return Tuple<T&&...>(static_cast <T&&>(v)...);
462
481
}
482
+
483
+ template <class ... Tuples>
484
+ [[nodiscard]] constexpr decltype (auto ) tuple_cat(Tuples&&... tuples) noexcept
485
+ {
486
+ constexpr auto total_size = (std::tuple_size_v<std::remove_cvref_t <Tuples>> + ...);
487
+ constexpr auto indices = [&]
488
+ {
489
+ std::array<detail::TupleCatIndex, total_size> array{};
490
+ size_t i{};
491
+ for (std::size_t outer{}; auto tuple_size : {std::tuple_size_v<std::remove_cvref_t <Tuples>>...})
492
+ {
493
+ for (size_t inner{}; inner != tuple_size; ++inner)
494
+ {
495
+ array[i] = {outer, inner};
496
+ ++i;
497
+ }
498
+ ++outer;
499
+ }
500
+ return array;
501
+ }();
502
+ return [&]<std::size_t ... I>(std::index_sequence<I...>)
503
+ {
504
+ using Ret =
505
+ Tuple<std::tuple_element_t <indices[I].inner , std::remove_cvref_t <decltype (detail::get_nth<indices[I].outer >(
506
+ static_cast <Tuples&&>(tuples)...))>>...>;
507
+ return Ret{ltpl::get<indices[I].inner >(detail::get_nth<indices[I].outer >(static_cast <Tuples&&>(tuples)...))...};
508
+ }(std::make_index_sequence<total_size>{});
509
+ }
463
510
} // namespace ltpl
464
511
465
512
template <std::size_t I, class ... T>
0 commit comments