Tuesday, November 22, 2011

std::function

A colleague recently asked for suggestions on how to pass a pointer to a callback function without having the caller know whether the function is a free function or member function.  I suggested std::function (previously know as std::tr1::function or boost::function) but later realized I'd never actually used it.  Seems like now might be a good time for an experiment.

First, let's define a class that others might want to observe:
struct Caller
{
  typedef std::function< void() > Callback;
    
  void RegisterCallback( Callback const & callback )
  {
    callbacks.push_back( callback );
  }
    
  void Notify() const
  {
    std::for_each( callbacks.begin(), callbacks.end(), []( Callback const & callback )
    {
      callback();
    });
  }
    
  std::vector< Callback > callbacks;
};
Next, a free function we want to be called:
void GlobalFunction()
{
  std::cout << "GlobalFunction" << std::endl;
}
As well as a functor:
struct Functor
{
  void operator()()
  {
    std::cout << "Functor" << std::endl;
  }
};
And finally, a member function on an observing class:
struct Observer
{
  void Update()
  {
    std::cout << "Observer::Update" << std::endl;
  }
};
Hooking everything up:
  Caller caller;
    
  Observer observer;
    
  caller.RegisterCallback( &GlobalFunction );
  caller.RegisterCallback( Functor() );
  caller.RegisterCallback( std::bind( &Observer::Update, observer ) );
    
  caller.Notify();
Gives the output we'd expect:
GlobalFunction
Functor
Observer::Update
But how could we implement an UnregisterCallback method on the Caller class? std::function is neither LessThanComparable nor EqualityComparable so storing them in a set (ordered or otherwise) won't work. Seems that Boost.Signals might be a better fit for this task.

Saturday, March 26, 2011

projecteuler.net and C++ meta-programming

I was introduced to projecteuler.net at a recent Guelph Coffee & Code meeting. The concept's quite simple: math problems of increasing difficulty to be solved using your programming language of choice. Sounds fun, no? We had a look at the first problem on the list:
Add all the natural numbers below one thousand that are multiples of 3 or 5.

On the walk home, I found myself thinking about the problem and I wondered if it would be possible to use C++ template meta-programming to obtain the solution at compile time. Here's what I came up with:


template< int n >
struct sum_integers_up_to
{
static const int result =
(n * (n + 1)) / 2;
};

template< int upper_limit, int x >
struct sum_multiples
{
static const int result =
x * sum_integers_up_to< (upper_limit - 1)/ x >::result;
};

template< int upper_limit, int x, int y >
struct sum_two_multiples
{
static const int sum_of_multiples_of_x =
sum_multiples< upper_limit, x >::result;
static const int sum_of_multiples_of_y =
sum_multiples< upper_limit, y >::result;
static const int sum_of_multiples_of_xy =
sum_multiples< upper_limit, x*y >::result;

static const int result =
sum_of_multiples_of_x + sum_of_multiples_of_y - sum_of_multiples_of_xy;
};

int main()
{
return sum_two_multiples< 1000, 3, 5 >::result;
}

Having a look at the assembly code generated by MSVC, we see that it's about as minimal as it gets (spoiler alert!):

_main PROC
mov eax, 233168
ret 0
_main ENDP

One down, 328 to go...