Sunday, June 9, 2013

C++11 no floats in templates??? WTF???

Sigh... i have no idea why c++11 doesn't allow floats in templates...

template <float number>
struct Value
{
  static const float VALUE = number;
};

The crazier part is that they have allowed enough other syntax sugar that you can fake it.. So why not just support it in the first place??

#include <iostream>

template <int NUM, int DEN>
struct Float
{
    constexpr static float value() { return (float)NUM / (float)DEN; }
    static constexpr float VALUE = value();
};

template <class GRAD, class CONST>
struct LinearFunc
{
    static float func(float x) { return GRAD::VALUE*x + CONST::VALUE; }
};

int main()
{
    // Y = 0.333 x + 0.2
    // x=2, y=0.866
    std::cout << " func(2) = "
              << LinearFunc<Float<1,3>, Float<1,5> > ::func(2) << std::endl;
}

Wednesday, January 2, 2013

Arrays and sizeof fun.

Sizeof arrays is a rather large land mine in c/c++. Even the most experienced coders will often hack out a piece of code and suddenly come to a screeching halt half way in when they realize they are being an idiot(hopeful they realize...).

The problem is that arrays in C are supposed to be well arrays.. but people often use them as shortcut to define some small non-standard chunk of data, and then you have a nice little surprise waiting to happen when your later upgrading or re-factoring or just using that piece of code. (otherwise know as the "30 seconds saved, 3 hours wasted" coding style..)

Here is what happens when you use arrays as a replacement type:
#include <iostream>

void func(char c[5])
{
  std::cout << "sizeof(param,5):" << sizeof(c) << std::endl;
}

void func2(char c[14])
{
  std::cout << "sizeof(param,14):" << sizeof(c) << std::endl;
}

typedef char Typedefed[5];

void func3(Typedefed c)
{
  std::cout << "sizeof(typedef,5):" << sizeof(c) << std::endl;
}

int main()
{
  char a[5];

  std::cout << "sizeof(local,5):" << sizeof(a) << std::endl;
  func(a);
  func2(a);
  func3(a);
}


Result (yes it does compile even with the char[14] array being handed a char[5], segv surprise.. yummy!):
sizeof(local,5):5
sizeof(param,5):4
sizeof(param,14):4
sizeof(typedef,5):4

So whats going on.. well this is the unfortunate consequence a design decision in the Ansi C standard "6.2.2.1 Lvalues and function designators".

"Except when it is the operand of the sizeof operator or the unary & operator, or is a character string literal used to initialize an array of character type, or is a wide string literal used to initialize an array with element type compatible with wchar_t, an lvalue that has type ``array of type'' is converted to an expression that has type ``pointer to type'' that points to the initial element of the array and is not an lvalue. "

So to work around it your forced to take other measures. Generally I believe its a good idea to do it the right way first time and simply create a trivial struct for your primitive type, consider it a slightly bloated version of a typedef. Your alternatives to this are always passing a ref to the array, or always passing its size with it.


#include <iostream>
void wasteful(char* c, std::size_t s)
{
  std::cout << "sizeof(c):" << sizeof(c) << std::endl;
  std::cout << "sizeof(s):" << sizeof(s) << std::endl;
  std::cout << "wasted  :" << sizeof(c) + sizeof(s) - s << std::endl;

  std::cout << "used  :" << s << std::endl;
}

void easytoforget(char (&e)[5])
{
  std::cout << "sizeof(e):" << sizeof(e) << std::endl;  
};

struct Structed
{
  Structed(char* a)  { memcpy(a_,a,sizeof(a_)); }

  char a_[5];
};

void fixed(Structed e)
{
  std::cout << "sizeof(e):" << sizeof(e) << std::endl;  
};

int main()
{
  char a[5];
 
  std::cout << std::endl << "Solutions:" << std::endl;
  wasteful(a, sizeof(a));
  easytoforget(a);
  fixed(a);
}



Wednesday, December 5, 2012

Lecture notes for the design of the std::bind replace

Normally when I blog its for myself, this isn't profession programming, this is hack and slash programming at its best. I normally wander around a topic until I get board of it. Blog what I complete and move on.. I have hundreds of half written posts, incomplete code fragments, scratch notes and todo'ed ideas.. eh maybe someday ill get to them... And my blog posts are normally min on the explanation and max on the code rampage...

Unfortunately sooner or later you get asked to present something would form a logically concise and worth while presentation. and somehow the excuse "But Im not anything more that am just another com sci nut with a blog and to much free time.." doesn't work...

So here is the are the notes from my presentation on the std::bind replacement(in a non-ADHD form)

The conversion of current std::bind implementations into movable form and lessons learned in the process.


Intro


As the old saying goes it is often the journey that matters and not the destination. In this generation we tend to get distracted easily and fail to understand the point of taking the harder route since the destination is the same anyway. Engineering and Science is one of those "arts" that often benefit from taking the harder route. Make no mistake engineering and science is an art.. it can be the industrial bare bones application(like a 1970 "mobile" phone) or something as refined as an iPhone. The key difference is the engineer that created the piece of work, his know-how and his skill at applying it. By reinventing the wheel once in a while we engineers can often pick up on the original basis of the problem and the foundation of solution and with this new insight and knowledge read into the mind of the original designers, metaphorically pick his brain and re-imagine the solution into one suitable for a comparable problem.

Which is what i have done in a series of blog posts here

The problem

The Issue at hand: Currently std::bind and Lamdba’s don’t seem to be move compatible. The basic problem to we are discussing here is a next step logical step to perfect forwarding. That is a "Delayed perfect forwarding" or “Indirect perfect forwarding”. The idea of "perfect forwarding" is to determine if the object is moving or not and pass it on as such. "Delayed perfect forwarding" would be the idea performing a perfect forward move through to function in a delay lazy calling content. This effectively means “binding ”. Eg we move the function and current contexts data into the bind capture and move it out of the capture context at the actual moment of execution and fill in the last minute details. Current Lambda disallows this:
std::function<void ()> && evil_move_capture()
{
  std::thread t(thread_core);
  std::function<void ()> func = 
  [std::move(t)()]->void 
  {
    std::cout << "Joining the thread....\n";
    t.join();
  };

  func();
}
Resulting in these compile issues:
lambda_move.cpp: In function ' std::function<void ()> && evil_move_capture()':

lambda_move.cpp:17:6: error: capture of non-variable 'std'

<built-in>:0:0: note: 'namespace std { }' declared here
You can of course move on execution... but that misses the point of the capture vs parameters
std::function<void ()> && evil_create_func()
{
  std::thread t(thread_core);

  std::function<void ()> func = 
  [&]()->void 
  {
    std::thread t0(std::move(t));
    std::cout << "Joining the thread....\n";
    t0.join();
  };

  //works here but after return! 
  //func();

  return std::move(func);
}
And of course you can’t seem to do it with the current bind implementation. (Although it has been suggested to me that this a mistake in the compilers/libraries implementation and not the new standard)
std::function<void ()>&& evil_bind_capture()
{
  std::thread t(thread_core);
  //to check that its going to work normally
  //bind_f(std::move(t));

  auto func = std::bind(bind_f, std::move(t));
  func();
}
…/c++/4.7.0/functional:1206:35: error: cannot bind 'std::thread' lvalue to std::thread&&'

The solution

The simplest solution is to move into the capture context and then to always move out of it. Of course this misses some of the more subtle points but who cares.

Step 1: Create an inspectable class for the Captured data.

The basic reproduction of a tuple. std::tuple is the normal std declared by member object... reusing this idea will allow you to create more complex member inspection and self-documenting/self traiting class. Ie Im just doing this so that I can expand its functionally after the fact.. Points to note
  • This is a normal recursive implementation of a varaidic template. Creating an inspectable self-declaring object that is capable of known what its members are.
    • It removes a single param out of the list in params and using it as the main member of the struct and deriving from the recursive construct of the remaining.
  • The constructor accepts its params via std::move and performs perfect forwarding on them into the local storage.
The simplistic version is;
template <typename A, typename ...Args>
struct Obj : public Obj<Args...>
{};
The actual application is:
//The general case
template <typename A, typename ...Args>
struct MoveCapture : public MoveCapture<Args...>
{
  A a_;

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

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

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

Step 2: Expand the Capture class for retrieval

Now this stores the values. The problem of course is how to then retrieve them. This is the where the tuple rebuild comes into play. Points to note.
  • This is one of the another interesting variadic template techniques. Lets dub it "Parameter induction"
    • This is the idea of appending parameters to a list of variadic parameters instead of reducing it.
    • The control mech for this is of course the original reduction that is used when creating the object in the first place. The key difference is that the inducted list of outgoing objects does not have to match the original input list of objects.
Parameter induction. The simplistic version is;
Template <...I>
Control<R,RR....>::induct(I ....i)
{
  R r;
  Control<RR...>::induct(i..., convert(r));
};
The actual application is:
//The general case
template <typename A, typename ...Args>
struct MoveCapture : public MoveCapture<Args...>
{
  A a_;
  ...

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

//The terminal case
template <typename A>
struct MoveCapture<A>
{
  A a_;
  ...

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

Step 3a: Handling the early Capture of Placeholders

Now we can get the data in and out... But the next problem in the design is how do you handle the difference between a placeholder and the actual data being captured. Primary this just means that the placeholder type and object will appear in the parameter list. So in theory all you have to do is specialize the object to the placeholder as such Points to note:
  • This might on the surface seem simple but this one of more tricky items to make work
  • Pay special care to the “const” when using std::moved item. This is a nasty little trick that allows the const to slip around resulting in massive compiler errors and are very difficult to figure out.
Simplest usage
Template <R,…RR>
struct A {};

Template <special,…RR>
struct A<recreate<special>::type, RR...> {};
The actual application is:
template <int I, typename ...Args>
struct MoveCapture<const std::_Placeholder<I>, Args...> : public MoveCapture<Args...>
{};

Step 3b: Handling the resolution of early Captured and later passed Params

Further more there is a yet another catch 22 when you try to actually resolve out placeholders. You end up having 2 variable param lists to handle and the c++11 spec allows for only 1. So here is another interesting technique, variadic template chaining. Points to note:
  • Since the spec allows 1 list the only way to do this is via a list separator.. in this case that just happens to be a "struct" or "class" object.
  • It is probably wise to end this in a function call for reasons ill explain latter.
The simplistic form.
A<...X>::B<....Y>::C<...Z>::call<>(D...)
The actual application: Additional Points to note:
  • In this design the application of it is actually early. This one is in the constructor of the binder so that the objects are handed to the binder(possibly containing placeholders) and the objects forwarded on to the end call can differ in types.
template <typename ...P>
struct MovableSetup
{
  typedef void (*Func)(P&&...);

  template <typename ...H>
  static MovableBinder<Func,MoveCapture<H...>> setup(Func f, H ...h)
  {
    typedef MoveCapture<H...> Capture;
    Capture* capture =  new MoveCapture<H...>(std::forward<H>(h)...);

    return MovableBinder<Func,Capture>(f,capture);
  }
};

Step 4: Something for the future. A Compiler param deductor

Now the final lesson to learn(but not applied) is that there is a slight difference between the class or struct usage of the varadic template and the function usage of the varadic templates. This creates a sizable difference in the end usage and more importantly the ability of the usage. Points to note
  • In the case of functions they have the capability of deducing the types from the instances and forwarding that into the template. In contrast with as the struct or class type there is no instance of variables so it cant guess the type you have to tell it explicitly.
    • This means that if you wish to create type deducting systems from instantiated objects you will need to create a function wrapper to make it work auto-magically
  • This is why I suggested that you end your chained variadic templates with a function call so that it can deduce as much as possible and save you and the end user of the code the effort.
In the simplistic form its:
struct A<P....>
{};

A<....P> maker(P....p) { return new A<P…>(p…); }

Wednesday, November 21, 2012

movable std::bind with placeholders

And finally the placement compatible version of the movable binder.. from 2012/11/perfect-forwarding-bind-compatable-with.html. this is again using threads to show that it works as with move only objects.

Also this probably needs gcc to work as it has a special placeholder classes call std::_Placeholder<>. Also I had to work around a compiler bug that kills the variadic templates nasty little monster that one..

And I still havent done anything about the problem with copying the binder

Ok this code probably needs a bit of explanation
There are several parts to a binder/lambda
  1. The "Binder Object" this is the main body of the binder. in the following code its called "MovableBinder"
  2. The "Bound function" this is the function that is to be executed in at the later point. In the code below its the typedef or template param called "Func"
  3. The "Closure" this is the part of the binder that captures variables in the context that the binder was created in. In the code below its called "MoveCapture"
  4. The "Placeholder" these are placement markers that allow the parameters that are handed in to be jumbled around for the binding interface. In the below code i attempted to use standard std::placeholders. It hasnt really worked out so great.
  5. The "Parameters" these are the params passed to the bind at the point of its execution. In the following code they are cached into the "MoveHolder" class.
This main core of this code design is the MoveCapture.

On Construction it recurses down the varable param decimates the list to an aggregate object that caches 1 param "A" or the placeholder on each step.

On "call" it again recurses down the MoveCapture structure again but this time its its doing the exact opposite and inductively constructing a list of params into the variadic param list called "InArgs".. If it strikes a placeholder it simple retrieves that entry from the MoveHolders object. By the end of structure it has recreated the full param list for the bound function call.


#include <iostream>
#include <memory>
#include <utility>
#include <tuple>
#include <thread>
#include <functional>
#include <string>

template <typename ...H>
struct MoveHolder 
{
  typedef std::tuple<H...>  Tuple;
  Tuple values_;
  
  MoveHolder(H&& ...h) :
    values_(std::forward<H>(h)...)
  {}

  template <int I>
  typename std::tuple_element<I, Tuple>::type&& access()
  {
    return std::move(std::get<I>(std::move(values_)));
  }
};


template <typename A, typename ...Args> 
struct MoveCapture : public MoveCapture<Args...>
{
  A a_;

  MoveCapture(A&& a, Args&& ...args) :
    MoveCapture<Args...>(std::forward<Args>(args)...),
    a_(std::forward<A>(a))
  {
    std::cout << "DEBUG " << __LINE__ << "\n";
  }

  template <typename Func,
     typename H,
       typename ...InArgs>
  void call(Func& f,
       H&& holders,
       InArgs&& ...args)
  {
    std::cout << "DEBUG " << __LINE__ << "\n";

    MoveCapture<Args...>::call(f, 
          holders,
          std::forward<InArgs>(args)...,
          std::move(a_));
  }
};

template <typename A> 
struct MoveCapture<A>
{
  A a_;

  MoveCapture(A&& a) :
    a_(std::forward<A>(a))
  {
    std::cout << "DEBUG " << __LINE__ << "\n";
  }

  template <typename Func,
     typename H,
       typename ...InArgs>
  void call(Func& f,
       H& holders,
       InArgs&& ...args)
  {
    std::cout << "DEBUG " << __LINE__ << "\n";

    f(std::forward<InArgs>(args)...,
      std::move(a_));
  }
};

template <int I, typename ...Args>
struct MoveCapture<const std::_Placeholder<I>, Args...> : public MoveCapture<Args...>
{
  enum { Index = I };
  
  MoveCapture(const std::_Placeholder<I>& h, Args&& ...args) :
    MoveCapture<Args...>(std::forward<Args>(args)...)
  {
    std::cout << "DEBUG " << __LINE__ << "\n";
  }

  //WARNING complier BUG!
  // COMMENTING THIS WILL CAUSE "call" to fail build
  template <typename H>
  void access(H& holders)
  {
    std::cout << I << "\n";
  }
  //END BUG

  template <typename Func,
     typename H,
       typename ...InArgs>
  void call(Func& f,
       H& holders,
       InArgs&& ...args)
  {
    std::cout << "DEBUG " << __LINE__ << "\n";

    MoveCapture<Args...>::call(f,
          holders,
          std::forward<InArgs>(args)...,
          std::move(holders.access<I-1>()));
  }
};

template <int I>
struct MoveCapture<const std::_Placeholder<I>>
{
  MoveCapture(const std::_Placeholder<I>& h) 
  {
    std::cout << "DEBUG " << __LINE__ << "\n";    
  }

  //WARNING complier BUG!
  // COMMENTING THIS WILL CAUSE "call" to fail build
  template <typename H>
  void access(H& holders)
  {
    std::cout << I << "\n";
  }
  //END BUG

  template <typename Func,
     typename H,
       typename ...InArgs>
  void call(Func& f,
       H& holders,
       InArgs&& ...args)
  {
    std::cout << "DEBUG " << __LINE__ << "\n";

    f(std::forward<InArgs>(args)...,
      std::move(holders.access<(I-1)>()));
  }
};

//template <typename ...P>
template <typename Func, typename Capture>
class MovableBinder
{
private:
  Func func_;
  Capture* capture_;

public:
  MovableBinder(Func func, Capture* cap) :
    func_(func),
    capture_(cap)
  {}

  ~MovableBinder()
  {
    if (capture_!= NULL)
      delete capture_ ;
  }

  template <typename ...V>
  void operator()(V&& ...v)
  {
    std::cout << "DEBUG " << __LINE__ << "\n";
    MoveHolder<V...> holders(std::forward<V>(v)...);
    capture_->call(func_, holders);
  }
};

template <typename ...P>
struct MovableSetup
{
  typedef void (*Func)(P&&...);

  template <typename ...H>
  static MovableBinder<Func,MoveCapture<H...>> setup(Func f, H ...h)
  {
    typedef MoveCapture<H...> Capture;

    std::cout << "DEBUG " << __LINE__ << "\n";
    Capture* capture =  new MoveCapture<H...>(std::forward<H>(h)...);
    return MovableBinder<Func,Capture>(f,capture);
  }
};

void hello(double&& done)
{
  std::cout << done << "\n";
}  

void hello2(double&& done1,
     double&& done2)
{
  std::cout << " part1:" << done1 
     << " part2:" << done2 
     << "\n";
}  

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();
}

int main()
{
  std::cout << "******** MANUAL USAGE **********\n";
  
  MoveCapture<const std::_Placeholder<1> > capture(std::placeholders::_1);
  MoveHolder<double> param(1.23);
  std::cout << param.access<0>() << "\n";
  
  capture.call(hello, param);
  
  std::cout << "******** NORMAL USAGE *********\n";
  
  auto movable_binder_1a = MovableSetup<double>::setup<const std::_Placeholder<1> >(hello,std::placeholders::_1);
  movable_binder_1a(1.34);

  auto movable_binder_1b = MovableSetup<double>::setup(hello,3.14);
  movable_binder_1b();

  auto movable_binder_2a = 
    MovableSetup<double, double>::setup<const std::_Placeholder<1>,
       const std::_Placeholder<2>>
          (hello2, std::placeholders::_1, std::placeholders::_2);
  movable_binder_2a(4.56,1.37);

  auto movable_binder_2b = 
          MovableSetup<double, double>::setup<double,
           double>
          (hello2,492.54, 743.293);
  movable_binder_2b();

  auto movable_binder_2c = 
          MovableSetup<double, double>::setup<double,
       const std::_Placeholder<2>>
          (hello2,492.54, std::placeholders::_2);
  movable_binder_2c(4.56,1.37);  //trash param 1

  std::cout << "******** THREAD BIND USAGE *********\n";

  std::thread tc(thread_core);
  auto movable_binder_tc = 
    MovableSetup<std::thread>::setup(join_thread, std::move(tc));
  movable_binder_tc();

  std::thread td(thread_core);
  auto movable_binder_td = 
    MovableSetup<std::thread>::setup<const std::_Placeholder<1> >(join_thread, std::placeholders::_1);
  movable_binder_td(std::move(td));

}

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();

}

c++11 Variadic template expansion options

While hacking up this movable bind function I got distracted(as per usual) thinking about the range of possible variadic template expansions available to us.

I figure that there are 2 main choices to make when using the argument packed types.
  1. Argument expansion or Argument Recursion
  2. Direct or Indirect

Argument expansion is where you flatten out the argument with the .... and pass them on.
  • The direct form of this is to work the expansion on the Argument is self.
  • The indirect for is to use a helper function around the Argument and expand the function passing it each object.

Argument recursion is where you siphon off one or more arguments on each pass and call down into your templates for the next stage.

  • The direct form is to do this in your main struct or function
  • The indirect form of this is where you create an inner helper or core that handles the recursive part for you.

Heres a triplet of examples that show the main uses cases that I would expect to see.. I guess there might be more but nothing else comes to mind at the moment... 
#include <iostream>
#include <utility>

// Indirect recursive class expansion
template <typename Func, typename A, typename ...Args> 
struct CallForEachHelper
{
  static void call(Func & f, A && a, Args && ...args)
  {
    f(std::forward<A>(a));
    CallForEachHelper<Func, Args...>::call(f, args...);
  }
};

template <typename Func, typename A> 
struct CallForEachHelper<Func, A>
{
  static void call(Func & f, A && a)
  {
    f(std::forward<A>(a));
  }
};

template <typename Func, typename ...Args>
void CallForEachIndirect(Func & f, Args && ...args)
{
  CallForEachHelper<Func, Args...>::call(f, std::forward<Args>(args)...);
}

// Direct recursive function expansion
template <typename Func, typename Arg>
void CallForEachDirect(Func & f, Arg arg)
{
  f(std::forward<Arg>(arg));
}

template <typename Func, typename Arg, typename ...Args>
void CallForEachDirect(Func & f, Arg arg, Args && ...args)
{
  f(std::forward<Arg>(arg));
  CallForEachDirect<Func, Args...>(f, std::forward<Args>(args)...);
}

// direct non-recursive argument flattening
template <typename Func, typename ...Args>
void CallForAll(Func & f, Args && ...args)
{
  f(std::forward<Args>(args)...); //indirect argument flattening using std::forward
}

void foo(int a)
{
  std::cout << "a:" << a << "\n";
}

void foo3(int a, int b, int c)
{
  std::cout << "a:" << a 
     << " b:" << b
     << " c:" << c 
     << "\n";
}

int main()
{
  int a1=1;
  int a2=2;
  int a3=3;
    
  CallForEachIndirect(foo, a1, a2, a3);  // run foo on each item via helper class recursion
  CallForEachDirect(foo, a1, a2, a3);    // run foo on each item by direct recursion
  CallForAll(foo3, a1, a2, a3);          // run foo3 on all items in 1 shot.
}

Sunday, November 11, 2012

perfect forwarding std::bind - why is std::bind not compatable with std::move??

Update: I have since posted the generic form of this code over Here

This is another oddity in the new spec. the std::bind and lambda are not able to take std:move()'ed items. The crazy part is that the standards community went so far as to define a std::forward to achieve perfect forwarding and didn't even take the next logical step and create a perfect forwarding version of std::bind and lamba...

So I hacked up a perfect forwarding verion of std::bind. This version is the one parameter version of the perfect forwarding std::bind. Still working on the variadic template version for unlimited params.

#include <iostream>
#include <memory>
#include <utility>

class MoveOnlyObj
{
public:
  MoveOnlyObj(int val) :
  val_(val)
  {
    std::cout << "MoveOnlyObj() - " << val_ << "\n";
  }
  
  MoveOnlyObj(MoveOnlyObj&& obj) :
  val_(obj.val_)
  {
    std::cout << "MoveOnlyObj(&&) - " << val_ << "\n";
    obj.val_ = 0; //0 it to make it very visable
  }

  ~MoveOnlyObj()
  {
    std::cout << "~MoveOnlyObj - " << val_ << "\n";
  }

private:
  friend std::ostream& operator<<(std::ostream& out, const MoveOnlyObj& o);
  MoveOnlyObj(MoveOnlyObj& obj);
  
  int val_;
};

std::ostream& operator<<(std::ostream& out, const MoveOnlyObj& o)
{
  out << o.val_;
  return out;
}

  
//lets start with the basic
template <typename P>
class MovableBinder1
{
  typedef void (*F)(P&&);

private:
  F func_;
  P p0_;

public:
  MovableBinder1(F func, P&& p) :
    func_(func),
    p0_(std::forward<P>(p))
  {
    std::cout << "Moved" << p0_ << "\n";
  }

  MovableBinder1(F func, P& p) :
    func_(func),
    p0_(p)
  {
    std::cout << "Copied" << p0_ << "\n";
  }
    
  ~MovableBinder1()
  {
    std::cout << "~MovableBinder1\n";
  }

  void operator()()
  {
    (*func_)(std::forward<P>(p0_));
  }
};

void test_func(int&& i)
{
  std::cout << "test_func: " << i << "\n";
}

void move_func(MoveOnlyObj&& i)
{
  MoveOnlyObj taker(std::move(i));
  std::cout << "move_func: " << taker << "\n";
}

int main()
{
  MovableBinder1<int> movable_binder_1_rvalue(&test_func, 3);
  movable_binder_1_rvalue();

  int i=4;
  MovableBinder1<int> movable_binder_1_lvalue(&test_func, i);
  movable_binder_1_lvalue();

  MoveOnlyObj m(5);
  MovableBinder1<MoveOnlyObj> movable_binder_move_only(&move_func, std::move(m));
  movable_binder_move_only();
}

And the output looks like this:
Moved3
test_func: 3
Copied4
test_func: 4
MoveOnlyObj() - 5
MoveOnlyObj(&&) - 5
Moved5
MoveOnlyObj(&&) - 5
move_func: 5
~MoveOnlyObj - 5
~MovableBinder1
~MoveOnlyObj - 0
~MoveOnlyObj - 0
~MovableBinder1
~MovableBinder1


And here is the gripper... This one passes a thread in as the parameter..
#include <iostream>
#include <memory>
#include <utility>
#include <thread>

//lets start with the basic
template <typename P>
class MovableBinder1
{
  typedef void (*F)(P&&);

private:
  F func_;
  P p0_;

public:
  MovableBinder1(F func, P&& p) :
    func_(func),
    p0_(std::forward<P>(p))
  {}

  MovableBinder1(F func, P& p) :
    func_(func),
    p0_(p)
  {}
    
  ~MovableBinder1()
  {}

  void operator()()
  {
    (*func_)(std::forward<P>(p0_));
  }
};

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

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

int main()
{
  std::thread t(thread_core);
  MovableBinder1<std::thread> movable_binder_thread(&join_thread, std::move(t));

  movable_binder_thread();
}