Generic programming, as used by the std and boost packages, depends heavily on template tricks to extract data from specific data structures in a generic way. When I first tried using some of the boost libraries, I felt pretty clueless in getting them to do what I wanted. Hence this post.
Say you have a C struct like this one:

struct Foo {
  int a;
  int b;

Generic programming accesses the a and b members using a global get function and a property map:

template <typename T, typename PMAP>
int get(T &t, PMAP pmap);

What’s in the property map? In this case nothing. The magic happens in the templated specialization of get:

struct get_a {};
int get(Foo &foo, get_a)
  return foo.a;

Which you call like this:

Foo f1;
f1.a = 10;
std::cout << "a is " << get(f1, get_a()) << std::endl;

How’s it work and what’s the compiled result?

The get_a struct is empty; it contains no data members. When you call get, the compiler selects the get_a version since it’s the most specific specialization of get. From there, things get interesting. Constructing get_a() is a noop. Pushing it as a function argument is a noop. After inlining, get simply becomes f1.a.

Using a phony C struct as a function selector

Leave a Reply

Your email address will not be published. Required fields are marked *