Archive for the Template Metaprogramming Category

Arbitrary binding pt1 – What is boost::bind and why is it cool?

Posted in C++, Template Metaprogramming on April 22, 2012 by Crazy Eddie

The STL has always been a rather brilliant piece of generic coding. The principles applied created a rather wonderful set of tools that could be used for a variety of conditions without losing type safety and without introducing unnecessary coupling by forcing inheritance. The ability to write generic algorithms that work on any type matching a given concept really adds to the expressiveness and power of C++. Until the advent of boost::bind though, the actual, practical use of these generic algorithms was too painful to bother.

To understand what I mean by this claim, consider the following program that finds all employees that make more than 50k a year:

struct employee
{
    int salary() const;
private:
  // ...
};

// Write special function just to compare salary because binds don't nest:
bool makes_less_than(employee const& e, int amount)
{
    return e.salary() < amount;
}

std::vector<employee> find_all_that_make_50k(std::vector<employee> const& employees)
{
    std::vector<employee> rval;

    std::remove_copy_if(employees.begin(), employees.end(), std::back_inserter(rval), std::bind1st(std::ptr_fun(makes_less_than), 50000));

    return rval;
}

In reality you would either write a functor that does exactly what you need, inheriting from std::unary_function, or you’d just use a for loop because use of all these binds and can get really ugly really fast. Compare the above to the alternative version you can do with boost::bind or with the new std::bind.


std::vector<employee> find_all_that_make_50k(std::vector<employee> const& employees)
{
    std::vector<employee> rval;
 
    // standard version...
    std::remove_copy_if(employees.begin(), employees.end(), back_inserter(rval), bind(less<int>, bind(&employee::salary, _1), 50000));

    // boost version...
    std::remove_copy_if(employees.begin(), employees.end(), back_inserter(rval), bind(&employee::salary, _1) < 50000);

    return rval;
}

This bind construct is even more interesting that this. Say I have an object that will call a function when something happens and I want it to call a method on an object that only takes some of the arguments the other object supplies? In other words, consider what I would do here in this C++03 code:

struct does_something
{
    void set_callback(void (*)(int, double));
};

struct can_respond
{
    void functionA(double);
};

There’s really no reasonable way for me to bind those two things. The best kind of thing one might come up with is to use the observer pattern:

struct does_something_observer
{
    virtual ~does_something_observer() {}
    virtual respond(int, double) = 0;
};

struct does_something
{
    void set_observer(does_something_observer *);
};

struct can_respond : does_something_observer
{
    void function(double);
    void respond(int, double d) { function(d); }
};

This option is suboptimal for three reasons:

  1. It requires we couple can_respond to part of the interface of does_something by inheriting from its observer
  2. We can’t change constness. If we make the callback function const, then subclasses that change in response have to cast it away (dangerous). If we make it non-const then we can’t use const observers.
  3. We force can_respond to implement a signature it’s not interested in, it doesn’t care about the int

Furthermore, most observers have many signatures in them…which is why the Java API has “Adapters” you can inherit from when you only want to listen to one part of the signal interface. Not using this adapter requires that you implement all the functions in the observer interface even if only to make them empty. It’s just a bunch of extra garbage code that fills up the brain (because it has to read it and know why these empty functions are there) without doing anything.

However, when we add an arbitrary function object type like boost::function (which I describe on my old blog — go to “W0t” and follow there) we can get rid of both of these problems:

struct does_something
{
    void set_responder(function<void(int,double)>);
};

struct can_respond
{
    void function(double);
};

does_something ds;
can_respond cr;

ds.set_responder(bind(&can_respond::function, ref(cr), _2));

The great thing here is that we’ve created a 2 argument function object out of a binding that will only use 1 of those arguments to call a function that only accepts one of them. The binder object created by bind can take an arbitrary, implementation defined amount of arguments and they can be anything. Only upon being called (well, when the call has to be compiled) does the system check whether or not the target function can take the arguments supplied, whether they match types, or whether they can be converted and how to do it. Basically, when you assign the binder to the function object by calling set_responder it will attempt to compile operator () with the two arguments that function object’s signature represents. This then will decide what happens.

Using these concepts and adding some loop processing and connection management, the boost::signals and signals2 libraries create a signal/slot mechanism that really surpasses any of the alternatives in its expressive power and in helping keep the coupling to a minimum. Unlike any other event marshaling system, which all require adherence to some specific signature and/or inheritence from a particular object, this system allows you to connect events to any object that can respond to them…ignoring or accepting any information provided by the event source.

THAT is pretty darn cool and brilliantly expressive. It wouldn’t be even half as great without the arbitrary binder. How was this binder created? Stay tuned for the next episode of “Arbitrary Binding”: “How to write your own arbitrary binder”

An easier way to select types

Posted in cpp, Template Metaprogramming on February 16, 2011 by Crazy Eddie

The Boost Template Meta-Programming Library is a very powerful library but there are some things that become necessary that can make things really tough to read. One example is having to nest if ‘blocks’ instead of having an ‘else if’. Considder

template < typename T >
struct match_type
  : mpl::if_
    <
      std::is_same<T, mpl::true>
    , double
    , if_
      <
        std::is_same<T, int>
      , char*
      , long
      >::type
    >
{};

Imagine that this went on for 5 checks or more. It becomes quite ungainly.

With this specific example we could use an mpl::map and things would be much easier. What if we where doing something else though? What if we really did need to run some metafunction on T in order to decide?

So I decided to create something a bit simpler to work with, a sort of “select/case” mechanism though at this time it doesn’t exactly match the same semantics as your standard switch statement. At any rate, here it is:


#include <boost/mpl/identity.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/lambda.hpp>
#include <boost/mpl/placeholders.hpp>
#include <type_traits>

using namespace boost;
using namespace boost::mpl::placeholders;

template < typename Test, typename Result >
struct case_ : Result 
{
};
template < typename Result >
struct default_ : Result {};

struct null_ {};

template < typename Switch
         , typename C1 = null_
         , typename C2 = null_
         , typename C3 = null_
         , typename C4 = null_ >
struct select_ {};

template < typename Switch, typename C1Test, typename C1Result, typename C2, typename C3, typename C4 >
struct select_<Switch, case_<C1Test, C1Result>, C2, C3, C4>
  : mpl::if_
    <
      typename C1Test::template apply<Switch>::type
    , C1Result
    , select_<Switch, C2, C3, C4>
    >::type
{
};

template < typename Switch, typename C1Result, typename C2, typename C3, typename C4 >
struct select_<Switch, default_<C1Result>, typename C2, typename C3, typename C4 >
  : C1Result
{};

// test code...

#include <iostream>
#include <typeinfo>


template < typename Var >
struct test_select
  : select_
    < Var
    , case_
      <
        mpl::lambda< std::is_same<_, mpl::true_> >::type
      , mpl::identity<double> 
      >
    , case_
      <
        mpl::lambda< std::is_same<_, int> >::type
      , mpl::identity<char*>
      >
    , default_< mpl::identity<long> >
    >
{};


// select as metafunction class...

template < typename C1 = null_
         , typename C2 = null_
         , typename C3 = null_
         , typename C4 = null_ >
struct select
{
  template < typename Switch >
  struct apply : select_<Switch, C1,C2,C3,C4> {};
};

// test select as metafunction class.
typedef select
    < case_
      <
        mpl::lambda< std::is_same<_, mpl::true_> >::type
      , mpl::identity<double> 
      >
    , case_
      <
        mpl::lambda< std::is_same<double, int> >::type
      , mpl::identity<char*>
      >
    , default_< mpl::identity<long> >
    > my_select;

// visually verify answer
int main()
{
  std::cout << typeid( test_select<double>::type ).name() << std::endl;
  std::cout << typeid( my_select::apply<int>::type ).name() << std::endl;
}

This could be easily adjusted to run the second parameter to ‘case_’ as a metafunction instead of simply grabbing a type.

Hello world!

Posted in Template Metaprogramming on January 16, 2011 by Crazy Eddie

Yes, you can.

#include <boost/mpl/string.hpp>
#include <boost/mpl/insert.hpp>
#include <boost/mpl/end.hpp>

namespace mpl = boost::mpl;

template < typename S1, typename S2 >
struct concat 
  : mpl::insert
    <
      S1
    , typename mpl::end<S1>::type
    , S2
    > 
{};

typedef mpl::string<'hell', 'o'> hello;
typedef mpl::string<'worl', 'd!'> world;

typedef concat
< 
  concat
  <
    hello
  , mpl::string<' '> 
  >::type
  , world
>::type because_i_can;

#include <iostream>
int main()
{
  std::cout << mpl::c_str<because_i_can>::value << std::endl;
}

Follow

Get every new post delivered to your Inbox.