Jeroen and Noah Roberts, doing reflection in C++
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