Jeroen and Noah Roberts, doing reflection in C++

Discussion in 'C++' started by John Harrison, Mar 7, 2007.

  1. 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, Mar 7, 2007
    #1
    1. Advertising

  2. 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
    John Harrison, Mar 7, 2007
    #2
    1. Advertising

  3. John Harrison

    Piyo Guest

    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!!
    Piyo, Mar 7, 2007
    #3
  4. 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
    John Harrison, Mar 7, 2007
    #4
  5. John Harrison

    Piyo Guest

    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. :)
    Piyo, Mar 7, 2007
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Leonardo Maranh?o
    Replies:
    1
    Views:
    976
    Andrew Thompson
    Nov 22, 2004
  2. Johan Kohler
    Replies:
    5
    Views:
    513
    Paul Boddie
    Mar 8, 2005
  3. Ilias Lazaridis
    Replies:
    11
    Views:
    461
    George Sakkis
    Feb 19, 2008
  4. Steve Holden
    Replies:
    2
    Views:
    329
    Ilias Lazaridis
    Feb 18, 2008
  5. Roedy Green

    Oral Roberts Kult Kamp scandal

    Roedy Green, Nov 22, 2008, in forum: Java
    Replies:
    4
    Views:
    500
    Roedy Green
    Nov 24, 2008
Loading...

Share This Page