С++ Как сохранить пакет параметров в качестве переменной - программирование

С++ Как сохранить пакет параметров в качестве переменной

В настоящий момент у меня возникают проблемы с попыткой сохранить пакет параметров, это пример кода проекта:

template<typename Func, typename... Args>
void handleFunc(Func func, Args&&... args) {
    struct nest {
        Func nestFunc;
        Args... nestArgs; // I DONT KNOW WHAT TO DO HERE
        void setup(Func func, Args... args) {
            nestFunc = func;
            nestArgs = (args)...; // SO I CAN SET IT HERE
        }
        // Later I will forward this and run the function with its arguments
        unsigned process() {
            nestFunc(std::forward<Args>(nestArgs)...); // USE IT HERE
            return 0;
        }
    };
    nest* myNest;
    myNest->setup(func, (args)...);
}

Это пример всего, что связано с проблемой, мне нужно сохранить аргументы для позже в моей структуре гнезда. Кроме того, если у вас есть решение для его хранения, но чтобы установить, что оно отличается от моего, пожалуйста, сообщите мне об этом. Спасибо.

4b9b3361

Ответ 1

Вы должны использовать ::std::tuple<Args...> для его сохранения. Но тогда возникает вопрос, как распаковать его, когда вам это нужно. Для этого вам нужно использовать технику под названием "индексы".

Итак, вот ссылка на место, где я сделал примерно то, что вы хотите сделать. Самым значимым классом здесь является то, что центральная часть suspended_call.

https://bitbucket.org/omnifarious/sparkles/src/tip/sparkles/deferred.hpp?at=default

Немного, я извлечу наиболее релевантные биты и поставлю их с точки зрения вашего кода.

Эта строка:

auto saved_args = ::std::make_tuple(::std::move(args)...);

сохраняет аргументы в кортеж. Я использовал ::std::move там, и я думаю, что это правильно. Но возможно, я ошибаюсь, и я должен использовать ::std::forward. Я никогда не видел четкой разницы, кроме намерения сигнализации.

Код, который фактически выполняет вызов с сохраненными аргументами, можно найти здесь. Теперь этот код достаточно специфичен для того, что я делаю. Бит, который реализует трюк индексов, включает создание пакета целых чисел, который сопоставляет индексы для использования в качестве аргументов шаблона ::std::get<I>. После того, как у вас есть этот набор целых чисел, вы можете использовать его, чтобы развернуть вызов до ::std::get, чтобы получить все элементы кортежа как отдельные аргументы.

Я попытаюсь придумать код, который делает это относительно простым способом:

#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));
}

Многое из этого кода было заимствовано из этой страницы по трюку индексов.

Кроме того, этот тип образца, который вам придется немного адаптировать к конкретной ситуации. В принципе, просто позвоните call(nestFunc, saved_args) где-нибудь.

Ответ 2

Я знаю, что это было какое-то время, но у меня были подобные потребности, и я придумал это решение, надеюсь, что это поможет кому-то:

#include <functional>

template<typename Func, typename... Args>
struct nest {
    std::function<void()> callBack;

    void setup(Func func1, Args... args) {
        callBack = [func1, args...]()
        {
            (func1)(args...);
        };
    }

    unsigned process() {
        callBack();
        return 0;
    }
};

template<typename Func, typename... Args>
void handleFunc(Func func, Args&&... args) {
    nest<Func, Args...> myNest;
    myNest.setup(func, args...);
}