Инкапсуляция аргументов функции variadi c в экземпляре класса - PullRequest
3 голосов
/ 14 февраля 2020

Вот код с дырками:

template<typename... Args>
class A 
{

  typedef function_type = void(*)(Args...);

  public:
  void set_args(Args&& ... args)
  {
      // something magic manages to encapsulate
      // args in instance of A
  }
  void apply_args(function_type function)
  {
      // something magic manages to "retrieve"
      // the encapsulated args
      function(std::forward<Args>(args)...);
  }

};

Это было бы как-то возможно?

Ответы [ 2 ]

3 голосов
/ 14 февраля 2020

Вы можете сохранить аргументы шаблона в элементе данных класса типа std::tuple и использовать std::apply, чтобы применить сохраненные аргументы к предоставленной функции.

Итак, допустим, у вас есть класс Action, подобный этому:

template <typename... Args>
class Action {
    std::tuple<Args...> args_;

public:
    Action() = default;
    Action(Args&&... args)
        : args_(std::forward<Args>(args)...)
    {}

    void args(Args&&... args) {
        args_ = std::make_tuple<Args...>(std::forward<Args>(args)...);
    }

    template <typename F>
    void apply(F&& fun) {
        std::apply(std::forward<F&&>(fun), args_);
    }
};

, где вы устанавливаете аргументы через конструктор Action action(1, 2, 3); или через отдельную функцию action.set(3, 2, 1);.

Тогда ваш Основная функция может выглядеть следующим образом:

int main() {
    Action action(1, 2);

    action.apply([](int a, int b) {
        std::cout << "a + b = " << (a + b) << std::endl;
    });

    return 0;
}

Проверка Пример в реальном времени

1 голос
/ 14 февраля 2020

Вы можете использовать std :: tuple и std :: apply

#include <iostream>
#include <tuple>
#include <functional>
#include <string>

template <typename... Ts>
class A
{
    private:
        std::function<void (Ts...)> f;
        std::tuple<Ts...> args;    
    public:
        template <typename F>
        A(F&& func, Ts&&... args)
            : f(std::forward<F>(func)),
              args(std::make_tuple(std::forward<Ts>(args)...))
        {}

        void Invoke()
        {
            std::apply(f, args);
        }
};

template <typename F, typename... Args>
A<Args...> Create(F&& f, Args&&... args)
{
    return A<Args...>(std::forward<F>(f), std::forward<Args>(args)...);
}

int main()
{
    auto helloWorld = Create([] (std::string a, std::string b) { std::cout << a << ", " << b; }, std::string("Hello"), std::string("World!"));

    helloWorld.Invoke();
}
...