将模板参数包存储为非类模板的属性

时间:2019-03-17 10:06:01

标签: c++ c++11 templates parameter-passing variadic-templates

是否可以将传递给非类模板的构造函数的可变参数模板参数/参数包存储为该类的属性而无需将该类转换为类模板?

我目前正在开发一个具有以下签名的瘦包装器类(这里我仅创建了一个最小的示例以最小化复杂性):

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

参数包将传递到成员函数模板start<Function, ... Args>,并且当前不需要“存储” functionargs。完善的转发功能可用于该功能的进一步处理。

现在,我要实现的是如下签名(引入 Interface类):

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_;
};

尽管在上面的示例中不需要 Interface Class ,但通常是必需的,因为实例应存储在std::vector<std::unique_ptr<WrapperInterface>>中。

我已经阅读并尝试过How to store variadic template arguments?,但是这种方法需要将Wrapper变成类模板。

我认为需要类似于QThread *QThread::create(Function &&f, Args &&... args) implementation的内容。可悲的是,该代码对我来说太高级了。

您能引导我朝正确的方向前进吗?使用私有实现类模板可以吗?

1 个答案:

答案 0 :(得分:3)

您尝试做的事情称为类型擦除,这是一种非常有趣的技术(示例和无耻的自我促进here),但是您已经在std::function中为您完成了,所以您要做的就是使用std::function<void()>并使用std::bind或lambda捕获来存储参数:

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