Wednesday, February 17, 2010

Using mpl::for_each to fill a tuple

This article is actually a paste of something I wrote to comp.lang.c++ quite a while ago.


A while back I posted a question either here or to the boost user list about how to iterate through a vector of strings and perform a lexical cast on them into elements of a tuple. I was working with sqlite3 and found myself repeatedly writing code like so:

t.get<0>() = boost::lexical_cast<double>(vect[0]);
t.get<1>() = boost::lexical_cast<int>(vect[1]);
...

For each query I would invent. Certainly there seemed there should be a way to use metaprogramming to approach this problem. I could get here:

t.get<N>() = boost::lexical_cast< boost::tuples::element<N, TUP>::type >(vect[N]);

However, I couldn't figure how to insert that into a metaprogram. I figured it would have something to do with for_each but couldn't figure it out. When I approached whatever list I posted my question to I was sent to some library...I forget which one but it wasn't the answer (blog note: it was the phoenix library). Well, last night a light in my brain turned on. It's actually very simple once it dawns on one how to do it:

template < typename TUPLE >
struct tuple_assign
{
TUPLE & t;
std::vector< std::string > const& data;

tuple_assign(TUPLE & to, std::vector const& from) : t(to), data(from) {}

template < typename T>
void operator() (T) // T must be an mpl::int_
{
boost::tuples::get<T::value>(t) =
boost::lexical_cast< typename boost::tuples::element<T::value, TUPLE>::type >(data[T::value]);
}
};

Your calling code looks like so:

boost::tuple<double, int, std::string> t;
std::vector<std::string> d;
d += "5.2","42","HELLO!";

boost::mpl::for_each< boost::mpl::range<0,3> >(tuple_assign< boost::tuple<double,int,std::string> >(t,d));

The range can also be derived through the template system like so:

boost::mpl::range< 0, boost::tuples::length<boost::tuple<double,int,std::string> > >

Much safety can be placed on this system. I haven't done so here. This problem solved though, there's nothing stopping a generic query interface that could be used something like so:

tie(x, y, z) = query.run();

as well as an iterative interface that provides a similar tuple interface.

blog note: you'd need to override the = operator between tuples and some type returned by run() in order to get the necessary information to perform the above technique.

Sunday, February 7, 2010

Implementing std::tr1::function - pt 1

This is the first of what will be a series of articles about implementing a general purpose function wrapper that can contain any callable entity that responds to a particular signature. These articles will start with a much simpler problem and slowly add complexity until a full implementation has been created. Some insight will be taken from boost::function, the singly most commonly used implementation.

We'll start with something simple, working with a single, basic signature: void (int).


// abstract invoker
struct impl
{
virtual ~impl() {}
virtual void invoke(int) = 0;
virtual impl * clone() const = 0;
};

// invoker for function pointers.
struct fun_ptr_impl : impl
{
typedef void (*fun_ptr_t)(int);

fun_ptr_impl(fun_ptr_t f) : fun(f) {}
void invoke( int i ) { fun(i); }
impl * clone() const { return new fun_ptr_impl(*this); }

private:
fun_ptr_t fun;
};

// invoker for functors.
template < typename T >
struct object_impl : impl
{
object_impl(T const& t) : object(t) {}

void invoke( int i ) { return object(i); }

impl * clone() const { return new object_impl(object); }

private:
T object;
};

#include <boost/scoped_ptr.hpp>
#include <cassert>
// The function wrapper itself.
struct inheritance_function
{
typedef void (*fun_ptr_t)(int);

// construct with function pointer.
inheritance_function(fun_ptr_t f) : pimpl(new fun_ptr_impl(f))
{}
// construct with functor
template < typename Object >
inheritance_function(Object const& o) : pimpl(new object_impl<Object>(o))
{}
// copy
inheritance_function(inheritance_function const& ifun) : pimpl(ifun.pimpl->clone())
{}

// invoke the stored function.
void operator()(int i) const { return pimpl->invoke(i); }

// assign from inheritance_function
inheritance_function & operator = (inheritance_function const& ifun)
{
pimpl.reset(ifun.pimpl->clone());
return *this;
}
// assign from function pointer
inheritance_function & operator = (fun_ptr_t f)
{
pimpl.reset(new fun_ptr_impl(f));
return *this;
}
// assign from functor
template < typename Object >
inheritance_function & operator = (Object ob)
{
pimpl.reset(new object_impl<Object>(ob));
return *this;
}

private:
boost::scoped_ptr<impl> pimpl;
};

// some test code
#include <iostream>
void function(int x) { std::cout << "function(" << x << ")" << std::endl; }

struct object
{
void operator() (int x) { std::cout << "object::operator()(" << x << ")" << std::endl; }
};

int main()
{
inheritance_function f1 = function;
inheritance_function f2 = object();

f1(5); f2(6);

f2 = function;
f1 = object();

f1(5); f2(6);

f2 = f1;

f1(5); f2(6);
}


Pretty basic so far. There's much that is missing though and I'll continue adding as I go forward. All this code does is replace an internal invoker class based upon the assignment or construction argument passed in. If we get a function pointer then we create an invoker able to handle function pointers. Anything else we assume is a functor object. Granted, this could be in error but then the user of the class is attempting to use it inappropriately.

Now, keep in mind that this does not resemble boost::function at all. This is, however, the most straight forward method of implementing this behavior. If you read the boost::function website you'll find them explain why they do it differently:

The use of virtual functions tends to cause 'code bloat' on many compilers. When a class contains a virtual function, it is necessary to emit an additional function that classifies the type of the object. It has been our experience that these auxiliary functions increase the size of the executable significantly when many boost::function objects are used.

The next article will show how to make the above implementation take any argument and return any type. A new impl will need to be created to account for member function pointers. The article following that will explain how boost::function implements this functionality without using virtual functions.

Saturday, February 6, 2010

iterating a boost::tuple

The boost::tuple class is a subclass of boost::tuples::cons, which is
a list type structure that can be recursed in a manner similar to LISP
lists. The following code is an example of how to accomplish this.


#include <boost/tuple/tuple.hpp>
#include <iostream>

template < typename X >
void print_data(X const& x)
{
std::cout << " Type of elem: " << typeid(X).name() << std::endl;
std::cout << "Value of elem: " << x << std::endl;
}

template < typename H, typename T >
struct do_recurse
{
static void apply(boost::tuples::cons<H,T> const& c)
{
typedef boost::tuples::cons<H,T> current_cons;
typedef typename current_cons::tail_type tail_cons;
typedef typename tail_cons::head_type tail_head;
typedef typename tail_cons::tail_type tail_tail;

print_data(c.get_head());
do_recurse<tail_head, tail_tail>::apply(c.get_tail());
}
};

template < typename H >
struct do_recurse<H, boost::tuples::null_type>
{
static void apply(boost::tuples::cons<H,boost::tuples::null_type> const& c)
{
std::cout << " Type of last elem: " << typeid(H).name() << std::endl;
std::cout << "Value of last elem: " << c.get_head() << std::endl;
}
};

template < typename H, typename T >
void recurse(boost::tuples::cons<H,T> const& c)
{
do_recurse<H,T>::apply(c);
}


int main(int argc, char* argv[])
{
using namespace boost::tuples;
tuple<int, char, double> t(42,'A',3.14);

recurse(t);

std::cin.get();
return 0;
}

Wrapping the function in a struct is necessary because functions
cannot be partially specialized.