Created
December 27, 2025 19:51
-
-
Save dgodfrey206/260ef8f7befcd74f23b023366e760b35 to your computer and use it in GitHub Desktop.
Split argument list
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <utility> | |
| #include <string> | |
| #include <tuple> | |
| #include <print> | |
| #include <functional> | |
| #include <concepts> | |
| #include <memory> | |
| #include <iostream> | |
| namespace detail { | |
| template<std::size_t I> | |
| using make_sequence = std::make_index_sequence<I>; | |
| template<std::size_t... Is> | |
| using index = std::index_sequence<Is...>; | |
| template<int I, class Sequence> | |
| struct drop_before; | |
| template<std::size_t... Is> | |
| struct drop_before<0, index<Is...>> { | |
| using type = index<Is...>; | |
| }; | |
| template<int Idx> | |
| requires(Idx != 0) | |
| struct drop_before<Idx, index<>> { | |
| using type = index<>; | |
| }; | |
| template<int Idx, std::size_t I, std::size_t... Is> | |
| requires(Idx != 0) | |
| struct drop_before<Idx, index<I, Is...>> { | |
| using type = typename drop_before<Idx-1, index<Is...>>::type; | |
| }; | |
| // drop_after | |
| template<int I, class Seq1, class Seq2> | |
| struct drop_after; | |
| template<std::size_t... Is, std::size_t U, std::size_t... Us> | |
| struct drop_after<0, index<Is...>, index<U, Us...>> { | |
| using type = index<Is..., U>; | |
| }; | |
| template<int Idx, std::size_t... Is> | |
| requires(Idx != 0) | |
| struct drop_after<Idx, index<Is...>, index<>> { | |
| using type = index<Is...>; | |
| }; | |
| template<int Idx, std::size_t... Is, std::size_t J, std::size_t... Js> | |
| requires(Idx != 0) | |
| struct drop_after<Idx, index<Is...>, index<J, Js...>> { | |
| using type = typename drop_after<Idx-1, index<Is..., J>, index<Js...>>::type; | |
| }; | |
| template<int I, class Seq> | |
| using drop_before_t=typename drop_before<I,Seq>::type; | |
| template<int I, class Seq1, class Seq2> | |
| using drop_after_t=typename drop_after<I,Seq1,Seq2>::type; | |
| template<class F, class Tuple> | |
| decltype(auto) indexes_of( F&& f, Tuple&& tup ) { | |
| return std::invoke(std::forward<F>(f), | |
| detail::make_sequence<std::tuple_size_v<std::decay_t<Tuple>>>{}); | |
| } | |
| template<int I, class F, class Tuple> | |
| decltype(auto) split( F&& f, Tuple&& tuple ) { | |
| return indexes_of([f=std::forward<F>(f)]<std::size_t... Is>(detail::index<Is...>) { | |
| using S=detail::index<Is...>; | |
| using empty=detail::index<>; | |
| return std::invoke(decltype(f)(f), detail::drop_after_t<I-1,detail::index<>,S>{}, detail::drop_before_t<I,S>{}); | |
| }, std::forward<Tuple>(tuple)); | |
| } | |
| } | |
| template<typename Parent> | |
| struct C : public Parent { | |
| struct Base {}; | |
| template<class... Ts> | |
| struct inner : Base { | |
| inner(Ts... ts, std::size_t size) | |
| : data(size, 'X') { std::println("size_t"); } | |
| inner(Ts... ts, std::string data) | |
| : data(std::move(data)) { std::println("string"); } | |
| std::string data; | |
| }; | |
| template<int I, class Tuple> | |
| requires(I>0) | |
| decltype(auto) split( Tuple&& tup ) { | |
| return detail::split<I>([&]<std::size_t... Is, std::size_t... Us>(detail::index<Is...>, detail::index<Us...>) { | |
| return std::make_unique<inner< | |
| decltype(std::get<Is>(tup))... | |
| >>(std::get<Is>(tup)..., std::get<Us>(tup)...); | |
| }, std::forward<Tuple>(tup)); | |
| } | |
| template<int I, class Tuple> | |
| requires(I<0) | |
| decltype(auto) split( Tuple&& tup ) { | |
| using Td=std::decay_t<Tuple>; | |
| static constexpr auto N=std::tuple_size_v<Td>; | |
| return split<N-(-I)-1>(std::forward<Tuple>(tup)); | |
| } | |
| template<typename... ParentArgs> | |
| C(ParentArgs&&... args) | |
| : C(std::forward_as_tuple(std::forward<ParentArgs>(args)...)) {} | |
| private: | |
| template<class Tuple> | |
| requires (!std::same_as<std::decay_t<Tuple>, C>) | |
| C(Tuple&& tuple) | |
| : m_inner(split<std::tuple_size_v<Tuple>-1>(std::forward<Tuple>(tuple))) {} | |
| std::unique_ptr<Base> m_inner; | |
| }; | |
| struct D { | |
| int a; | |
| int b; | |
| }; | |
| template<class> | |
| struct Z; | |
| template<class... Ts> | |
| void foo() { | |
| C<D>::inner<Ts...> p(Ts{}..., "hi"); | |
| } | |
| int main() { | |
| using namespace std::literals; | |
| using namespace detail; | |
| auto test = C<D>(1, 3, "Hi"s); | |
| auto test2 = C<D>(1, 3, 10uz); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment