【发布时间】:2016-01-16 21:19:35
【问题描述】:
我正在创建一个作业队列。该作业将在线程 A 中创建,然后该作业将被发送到线程 B,线程 B 将完成该作业。作业完成后,作业将被发送回线程 A。
#include <functional>
#include <iostream>
#include <memory>
using namespace std;
template<typename T, typename... Args>
class Job
{
public:
Job(std::weak_ptr<T> &&wp, std::function<void(const Args&...)> &&cb)
: _cb(std::move(cb)),
_cbWithArgs(),
_owner(std::move(wp)) {}
public:
template<typename... RfTs>
void bind(RfTs&&... args)
{
// bind will copy args for three times.
_cbWithArgs = std::bind(_cb, std::forward<RfTs>(args)...);
}
void fire()
{
auto sp = _owner.lock();
if (sp)
{
_cbWithArgs();
}
}
private:
std::function<void(const Args& ...)> _cb;
std::function<void()> _cbWithArgs;
std::weak_ptr<T> _owner;
};
struct Args
{
Args() = default;
Args(const Args &args)
{
cout << "Copied" << endl;
}
};
struct Foo
{
void show(const Args &)
{
cout << "Foo" << endl;
}
};
int main()
{
using namespace std::placeholders;
shared_ptr<Foo> sf (new Foo());
Args args;
// Let's say here thread A created the job.
Job<Foo, Args> job(sf, std::bind(&Foo::show, sf.get(), _1));
// Here thread B has finished the job and bind the result to the
// job.
job.bind(args);
// Here, thread A will check the result.
job.fire();
}
上面的代码编译并工作。但它给出了以下结果(g++ 4.8.4 & clang 有相同的结果):
Copied
Copied
Copied
Foo
一共有三本!不能接受,我不知道我哪里做错了。为什么要三本?我用谷歌搜索并从这里找到一种方法:https://stackoverflow.com/a/16868401,它只复制一次参数。但它必须在构造函数中初始化绑定函数。
谢谢,Piotr Skotnicki。不幸的是,我没有 C++14 编译器。所以,让我们让 Args 可移动:
struct Args
{
Args() = default;
Args(const Args &args)
{
cout << "Copied" << endl;
}
Args(Args &&) = default;
Args& operator=(Args &&) = default;
};
现在,它只复制一次 :)
最后,我采用了来自该线程https://stackoverflow.com/a/16868151/5459549 的代码。我必须说,模板 gen_seq 是真正的 ART。
【问题讨论】:
标签: c++ templates c++11 bind variadic-templates