I am creating a job queue. The task will be created in stream A, then the task will be sent to stream B, and stream B will complete the task. After the task is completed, the task will be sent back to stream 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 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(); }
The above codes compile and work. But it gives the following results (g ++ 4.8.4 and clang have the same results):
Copied Copied Copied Foo
There are three copies! Unacceptable, I do not know where I was wrong. Why three copies? I googled and find the method from here: https://stackoverflow.com/a/166269/2126 , it only copies the parameters at a time. But it must initialize the bind function in the constructor.
Thank you, Peter Skotnitsky. Unfortunately, I don't have a C ++ 14 compiler. So, make Args movable:
struct Args { Args() = default; Args(const Args &args) { cout << "Copied" << endl; } Args(Args &&) = default; Args& operator=(Args &&) = default; };
Now it copies only once :)
Finally, I took the codes from this thread https://stackoverflow.com/a/312947/ I want to say that the gen_seq pattern is a true ART.