Musisz użyć ::std::tuple<Args...>
, aby go zapisać. Ale wtedy pojawia się pytanie, jak rozpakować go, kiedy go potrzebujesz. Do tego trzeba użyć techniki zwanej "indeksami".
Oto link do miejsca, w którym zrobiłem mniej więcej to, co chcesz zrobić. Najważniejszą klasą, która jest tutaj centralna, jest suspended_call
.
https://bitbucket.org/omnifarious/sparkles/src/tip/sparkles/deferred.hpp?at=default
W tylko trochę, będę wyodrębnić najistotniejsze kawałki i umieścić je pod względem kodu.
This line:
auto saved_args = ::std::make_tuple(::std::move(args)...);
oszczędza argumenty na krotki. Użyłem tam ::std::move
i uważam, że jest to słuszne. Ale jest możliwe, że się mylę i powinienem użyć ::std::forward
. Nigdy nie miałem jasności co do dokładnej różnicy, oprócz zamiaru sygnalizacji.
Kod, który faktycznie wykonuje połączenie z zapisanymi argumentami, można znaleźć pod numerem here. Teraz ten kod jest dość specyficzny dla dokładnie tego, co robię. Bit, który implementuje sztuczkę indeksów, polega na tworzeniu pakietu liczb całkowitych odwzorowującego indeksy, które będą używane jako argumenty szablonu ::std::get<I>
. Kiedy już masz ten pakiet liczb całkowitych, możesz użyć go do rozwinięcia połączenia do ::std::get
, aby uzyskać wszystkie elementy krotki jako indywidualne argumenty.
Postaram się wymyślić kodu, który robi to w stosunkowo prosty sposób:
#include <tuple>
#include <cstddef>
#include <string>
#include <utility>
template < ::std::size_t... Indices>
struct indices {};
template < ::std::size_t N, ::std::size_t... Is>
struct build_indices : build_indices<N-1, N-1, Is...>
{};
template < ::std::size_t... Is>
struct build_indices<0, Is...> : indices<Is...>
{};
template <typename FuncT, typename ArgTuple, ::std::size_t... Indices>
auto call(const FuncT &f, ArgTuple &&args, const indices<Indices...> &)
-> decltype(f(::std::get<Indices>(::std::forward<ArgTuple>(args))...))
{
return ::std::move(f(::std::get<Indices>(::std::forward<ArgTuple>(args))...));
}
template <typename FuncT, typename ArgTuple>
auto call(const FuncT &f, ArgTuple &&args)
-> decltype(call(f, args,
build_indices< ::std::tuple_size<ArgTuple>::value>{}))
{
const build_indices< ::std::tuple_size<ArgTuple>::value> indices;
return ::std::move(call(f, ::std::move(args), indices));
}
int myfunc(::std::string name, const unsigned int foo)
{
return 0;
}
int foo(::std::tuple< ::std::string, const unsigned int> saved_args)
{
return call(myfunc, ::std::move(saved_args));
}
Dużo tego kodu została zapożyczona z this page on the indices trick.
To także rodzaj próbki, którą trzeba nieco dostosować do swojej konkretnej sytuacji. Zasadniczo, wystarczy zadzwonić pod numer call(nestFunc, saved_args)
.
'std :: krotki' - również, 'std :: bind' i 'std :: function' i wszystkie fajne rzeczy. –
Xeo