将模板参数包存储为非 class 模板的属性
Store template parameter pack as a attribute of a non class template
是否可以将传递给非 class 模板的构造函数的可变参数模板参数/参数包存储为 class 的属性而无需 将 class 变成 class 模板?
我目前正在开发一个精简的包装器 class(我在这里只创建了一个最小的示例以尽量减少复杂性),它具有以下签名:
class Wrapper final {
public:
template <typename Function, typename... Args>
auto start(Function&& function, Args&&... args) -> void;
};
参数包传递给成员函数模板start<Function, ... Args>
,目前不需要"store"function
或args
。完美转发用于该功能内的进一步处理。
现在,我想实现的是如下签名(引入一个接口[=52=]):
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_;
};
虽然在上面的例子中不需要接口[=52=],但通常是必需的,因为实例应该存储在std::vector<std::unique_ptr<WrapperInterface>>
中。
我已经阅读并尝试过 How to store variadic template arguments?,但该方法需要将 Wrapper
转换为 class 模板。
我认为需要类似于 QThread *QThread::create(Function &&f, Args &&... args)
implementation 的内容。可悲的是,代码对我来说太高级了。
你能指导我正确的方向吗?是否可以使用私有实现 class 模板?
你正在尝试做的事情叫做类型擦除,这是一个非常有趣的技术(例子和无耻的自我推销 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)...);
}
是否可以将传递给非 class 模板的构造函数的可变参数模板参数/参数包存储为 class 的属性而无需 将 class 变成 class 模板?
我目前正在开发一个精简的包装器 class(我在这里只创建了一个最小的示例以尽量减少复杂性),它具有以下签名:
class Wrapper final {
public:
template <typename Function, typename... Args>
auto start(Function&& function, Args&&... args) -> void;
};
参数包传递给成员函数模板start<Function, ... Args>
,目前不需要"store"function
或args
。完美转发用于该功能内的进一步处理。
现在,我想实现的是如下签名(引入一个接口[=52=]):
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_;
};
虽然在上面的例子中不需要接口[=52=],但通常是必需的,因为实例应该存储在std::vector<std::unique_ptr<WrapperInterface>>
中。
我已经阅读并尝试过 How to store variadic template arguments?,但该方法需要将 Wrapper
转换为 class 模板。
我认为需要类似于 QThread *QThread::create(Function &&f, Args &&... args)
implementation 的内容。可悲的是,代码对我来说太高级了。
你能指导我正确的方向吗?是否可以使用私有实现 class 模板?
你正在尝试做的事情叫做类型擦除,这是一个非常有趣的技术(例子和无耻的自我推销 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)...);
}