Mar*_*tin 2 c++ struct function wrapper variadic-templates
我已经在堆栈溢出和谷歌上运行了几个小时了。我似乎无法理解如何在包装结构中存储函数指针及其参数。
下面的类包装了一个函数(在本例中是一个带有模板化返回类型和参数的打包任务)。下面列出了包装器的主要部分。
编辑:我不使用 std::function 的原因是因为包装器(ThreadTask)包装了一个 std::packaged_task ,该任务被移动到线程安全双端队列中。Packaged_task 是可移动构建的,并且不支持复制,而 std::function 则支持复制。因此我制作了一个定制包装。
编译器给出错误并指出该函数不接受 0 个参数。但我不知道如何传递参数/存储它们。
class ThreadTask {
struct BaseInterface {
virtual void Call() = 0;
virtual ~BaseInterface() {};
};
std::unique_ptr<BaseInterface> mImplementation;
template <typename F, typename...Args>
struct BaseFunc : BaseInterface {
F func;
BaseFunc(F&& f, Args... args) : func(std::move(f)) {}
void Call() { func(); }
};
};
Run Code Online (Sandbox Code Playgroud)
我尝试过以不同的方式解开这些论点,但我似乎无法使其发挥作用。我想我应该通过 std::forward 转发它们,但我不知道如何存储参数
我建议使用,std::function但如果您出于某种原因不想使用它,您可以扩展当前的类以存储参数std::tuple,然后使用std::apply“解包”并使用存储的参数调用该函数。
例子:
class ThreadTask {
public:
struct BaseInterface {
virtual ~BaseInterface() = default;
virtual void operator()() = 0;
};
std::unique_ptr<BaseInterface> mImplementation;
template <typename F, typename... Args>
struct BaseFunc : BaseInterface {
BaseFunc(F f, Args... args)
: func(std::move(f)), m_args{std::move(args)...} {}
void operator()() override {
std::apply(func, m_args);
}
F func;
std::tuple<Args...> m_args;
};
};
Run Code Online (Sandbox Code Playgroud)
使用示例:
void foo(int x, double y) {
std::cout << "got " << x << " and " << y << '\n';
}
int main() {
ThreadTask::BaseFunc bf{&foo, 12, 3.14159};
bf();
}
Run Code Online (Sandbox Code Playgroud)
注意:我更改Call()为看起来更合适的内容并为演示operator()()创建了成员。public