Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Jeroen and Noah Roberts, doing reflection in C++

1 view
Skip to first unread message

John Harrison

unread,
Mar 7, 2007, 12:28:28 AM3/7/07
to
Jeroen recently asked a question where he was trying to put arbitary
types onto a list and then do something useful with them afterwards.

Not possible I said, in my usual tetchy manner.

Noah Roberts then pointed me to the boost::any type.

Makes no difference I said.

Well having thought about it, I've changed my mind. The following code
allows a library user to put values of arbitary types onto a list, and
then print them out afterwards. Obviously the user must provide a
function to do the printing. This is done by specialising a function
template provided by the library.

Here's the code, comments welcome. This is a new technique to me.

// library.h
#ifndef LIBRARY_H
#define LIBRARY_H

#include <boost/any.hpp>
#include <list>
#include <map>
#include <typeinfo>
#include <functional>

struct typeinfo_lessthan : public std::binary_function<const
std::type_info*, const std::type_info*, bool>
{
bool operator()(const std::type_info* x, const std::type_info* y) const
{
/* dinkumware implementation of typeinfo::before returns int for some
reason */
return x->before(*y) != 0;
}
};

typedef std::list<boost::any> value_list_type;
typedef std::map<const std::type_info*, void (*)(boost::any),
typeinfo_lessthan> method_map_type;

extern value_list_type value_list;
extern method_map_type print_map;

template <class T>
void print(boost::any);

template <class T>
void add_to_list(const T& value)
{
boost::any any_value(value);
value_list.push_back(any_value);
print_map[&typeid(T)] = print<T>;
}

inline void print_value(boost::any value)
{
(*print_map[&value.type()])(value);
}

#endif

// main.cpp
#include <iostream>
#include <vector>
#include "library.h"

template <>
void print<int>(boost::any x)
{
std::cout << "int=" << *boost::any_cast<int>(&x) << '\n';
}

template <>
void print<double>(boost::any x)
{
std::cout << "double=" << *boost::any_cast<double>(&x) << '\n';
}

template <>
void print< std::vector<int> >(boost::any x)
{
std::vector<int>& v = *boost::any_cast< std::vector<int> >(&x);
std::cout << "vector=";
for (std::vector<int>::const_iterator i = v.begin(); i != v.end(); ++i)
std::cout << *i << ' ';
std::cout << '\n';
}

int main()
{
add_to_list(1);
add_to_list(2.0);
std::vector<int> v(4, 3);
add_to_list(v);
for (value_list_type::const_iterator i = value_list.begin(); i !=
value_list.end(); ++i)
{
print_value(*i);
}
}

john

John Harrison

unread,
Mar 7, 2007, 12:40:17 AM3/7/07
to
Thinking about it a little more the library could provide a default
implementation of the print routine, like this


template <class T>
void print(boost::any x)
{
std::cout << x.type().name() << '=' << *boost::any_cast<T>(&x) << '\n';
}

This would mean the specialisations for int and double of this function
in the original code could be removed.

john

Piyo

unread,
Mar 7, 2007, 1:35:40 AM3/7/07
to
John Harrison wrote:

>
> Here's the code, comments welcome. This is a new technique to me.

Welcome to the wonderful world of boost :) It's an awesome library
that should be dist'ed with EVERY single compiler and should be
taught in all classes that teach C++ :)

I learn about a new part of boost everyday myself.

My Motto:
Q: How do I do this?
A: Did you check boost first? :)

Since you just discovered any (unbound variant types) you might
want to invest some time in boost::variant (bounded variant types).
Why limit yourself to a limited set of types when any can REALLY
contain any. Well, in practical applications, the number of actual
types used in your variant type is limited. If you enumerate these,
apriori, you can add some pretty nifty functionality such as the
visitor pattern on top of it. Using any makes it difficult to
apply (not impossible) the visitor pattern whereas variant practically
gives it for free.

Good Luck with that!!

John Harrison

unread,
Mar 7, 2007, 2:17:59 AM3/7/07
to
Piyo wrote:
> John Harrison wrote:
>
>>
>> Here's the code, comments welcome. This is a new technique to me.
>
>
> Welcome to the wonderful world of boost :) It's an awesome library
> that should be dist'ed with EVERY single compiler and should be
> taught in all classes that teach C++ :)
>
> I learn about a new part of boost everyday myself.
>
> My Motto:
> Q: How do I do this?
> A: Did you check boost first? :)
>
> Since you just discovered any (unbound variant types) you might
> want to invest some time in boost::variant (bounded variant types).

I was aware of boost::any previously, it was the idea of storing
typeinfo in a map to look up an associated template function that was
new for me. In my code, within the template function print<T>, you do
have access to the type of the original value before it was placed into
boost::any. This was what I had said was impossible.

> Why limit yourself to a limited set of types when any can REALLY
> contain any. Well, in practical applications, the number of actual
> types used in your variant type is limited. If you enumerate these,
> apriori, you can add some pretty nifty functionality such as the
> visitor pattern on top of it. Using any makes it difficult to
> apply (not impossible) the visitor pattern whereas variant practically
> gives it for free.
>
> Good Luck with that!!

I'll have a good look at variant, looks interesting.

john

Piyo

unread,
Mar 7, 2007, 2:50:37 AM3/7/07
to
John Harrison wrote:
>
> I was aware of boost::any previously, it was the idea of storing
> typeinfo in a map to look up an associated template function that was
> new for me. In my code, within the template function print<T>, you do
> have access to the type of the original value before it was placed into
> boost::any. This was what I had said was impossible.

Sorry, my misunderstanding on what you found to be new. :)

0 new messages