Сохраните пакет параметров шаблона как атрибут шаблона не класса - PullRequest
1 голос
/ 17 марта 2019

Можно ли сохранить аргументы / пакет параметров шаблона переменной, переданные в конструктор шаблона не класса, как атрибут этого класса без превращения этого класса в шаблон класса?

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

class Wrapper final {
 public:
  template <typename Function, typename... Args>
  auto start(Function&& function, Args&&... args) -> void;
};

Пакет параметров передается в шаблон функции-члена start<Function, ... Args>и в настоящее время нет необходимости «хранить» либо function, либо args.Совершенная переадресация используется для дальнейшей обработки в этой функции.

Теперь я хотел бы добиться подписи (введение интерфейса класса ):

class WrapperInterface {
 public:
  virtual ~WrapperInterface() = default;

  virtual auto start() -> void = 0;
};

// TODO(2019-03-17 by wolters) The following is non-working pseudo-code.
class Wrapper final : public WrapperInterface {
 public:
  template <typename Function, typename... Args>
  explicit Wrapper(Function&& function, Args&&... args)
      : function_{function}, args_{args} {
    // NOOP
  }

  auto start() -> void {
    // TODO(2019-03-17 by wolters) Invoke `function_` with `args_`.
    function_(args);
  }

 private:
  std::function<???> function_;
  std::tuple<???> args_;
};

Тогда Wrapper можно использовать следующим образом:

class WrapperClient final {
 public:
  WrapperClient() : wrapper_{[this](){
    // std::cout << "started\n";
  }} {
    // NOOP
  }

 private:
  Wrapper wrapper_;
};

Хотя класс интерфейса не требуется в приведенном выше примере, он требуется в целом, поскольку экземпляры должны бытьхранится в std::vector<std::unique_ptr<WrapperInterface>>.

Я прочитал и попробовал Как хранить аргументы шаблона variadic? , но этот подход требует превращения Wrapper в шаблон класса.

Я думаю, что-то похожее на реализацию QThread *QThread::create(Function &&f, Args &&... args) требуется.К сожалению, этот код слишком сложен для меня.

Можете ли вы направить меня в правильном направлении?Возможно ли это с помощью закрытого шаблона класса реализации?

1 Ответ

3 голосов
/ 17 марта 2019

То, что вы пытаетесь сделать, называется стиранием типа, что является очень интересной техникой (пример и бесстыдное самореклама здесь ), но это уже сделано для вас в std::function, поэтому все вам нужно использовать std::function<void()> и использовать std::bind или лямбда-захват для хранения аргументов:

template <typename Function, typename... Args>
std::function<void()> wrap(Function&& function, Args&&... args)
{
    return [=] { function(args); };
    // or return std::bind(std::forward<Function>(function), std::forward<Args>(args)...);
}
...