Tuesday, November 13, 2012

perfect forwarding std::bind replacement compatable with std::move

And without any more messing around here is the generic version of the movable std::bind replacement.

  1. This version doesnt handle place holders yet.
  2. There is probably problems if you try to copy it
Update: I since added a placeholder version here
#include <iostream>
#include <memory>
#include <utility>
#include <thread>

//A helper class for storage and stitching params together
template <typename A, typename ...Args> 
struct MoveHelper : public MoveHelper<Args...>
{
  A a_;

  MoveHelper(A&& a, Args&& ...args) :
    MoveHelper<Args...>(std::forward<Args>(args)...),
    a_(std::forward<A>(a))
  {}

  template <typename Func, typename ...InArgs>
  void call(Func& f, InArgs && ...args)
  {
    MoveHelper<Args...>::call(f,
         std::forward(args)..., 
         std::move(a_));
  }
};

//The helpers terminal case
template <typename A> 
struct MoveHelper<A>
{
  A a_;

  MoveHelper(A&& a) :
    a_(std::forward<A>(a))
  {}

  template <typename Func, typename ...InArgs>
  void call(Func& f, InArgs && ...args)
  {
    f(std::forward<A>(args)...,
      std::forward<A>(a_));
  }
};

//the Main std::bind movable replacement
template <typename ...P>
class MovableBinder
{
  typedef void (*F)(P&&...);

private:
  F func_;
  MoveHelper<P...> help_;

public:
  MovableBinder(F func, P&& ...p) :
    func_(func),
    help_(std::forward<P>(p)...)
  {}

  MovableBinder(F func, P& ...p) :
    func_(func),
    help_(p...)
  {}
    
  ~MovableBinder()
  {}

  void operator()()
  {
    help_.call(func_);
  }
};

//And the test with threads.. the ultimate move only object...

void thread_core() {
  std::this_thread::sleep_for(std::chrono::seconds(2));
}

void join_thread(std::thread&& t1)
{
  std::cout << "Joining the thread....\n";
  t1.join();
}  

void join_threads(std::thread&& t1, std::thread&& t2)
{
  std::cout << "Joining the threads....\n";
  t1.join();
  t2.join();
}  

int main()
{
  std::thread ta(thread_core);
  std::thread tb(thread_core);
  MovableBinder<std::thread, std::thread> movable_binder_threads(&join_threads, std::move(ta),std::move(tb));

  movable_binder_threads();

  std::thread tc(thread_core);
  MovableBinder<std::thread> movable_binder_thread(&join_thread, std::move(tc));

  movable_binder_thread();

}

No comments:

Post a Comment