MACE  1.0.0
 All Classes Namespaces Files Functions Variables Enumerations Defines
Type Info
Reflect Library

Expose and query type names, members, and methods. More...

Often times it is helpful to have access to the string name of a class type, particularlly when you are putting print statements in templated code. This information is made available through a very simple templated method.

    reflect::get_typename<uint32_t>(); // return "uint32_t"
    reflect::get_typename<std::vector<uint32_t> >(); // return "std::vector<uint32_t>"

These names will be the same on all compilers so long as you utilize one of the following macro:

    MACE_REFLECT( your_namespace::your_class )
    MACE_REFLECT_TYPEINFO_ALIAS( your_namespace::your_class, "AkaMyClass" )

Member Visitors (to JSON example)

To reflect the members of a struct you want to use one of the following macros which automatically include MACE_REFLECT_TYPEINFO for the class name.

MACE_REFLECT( Class, MemberSequence)
MACE_REFLECT_DERIVED( Class, BaseSequence, MemberSequence)

  struct A {  std::string hello; };
  struct B : A { 
    std::string world;  
    int other;
  };

  MACE_REFLECT( A, (hello) )
  MACE_REFLECT_DERIVED( B, (A), (world)(other) )

You can then convert these types to json by defining a visitor:

template<typename T>
struct to_json_visitor {
    to_json_visitor( const T& v, std::ostream& _os ):val(v),os(_os),i(0){}

    template<typename MemberPtr, MemberPtr m>
    void operator()( const char* name )const {
      if( i == 0 ) os << "{";    
      os<<"\""<<name<<"\":";
      to_json( val.*m, os);
      if( i != mace::reflect::reflector<T>::total_member_count-1 ) os << ",";
      if( i == mace::reflect::reflector<T>::total_member_count-1 ) os << "}";
      ++i;
    }
    mutable int i;
    const T& val;
    std::ostream& os;
};

Then use the reflect::reflector<T> to visit the members.

template<typename T>
void to_json( const T& v, std::ostream& os ) {
    mace::reflect::reflector<T>::visit( to_json_visitor<T>( v, os ) );
}

When combined with the following base cases:

template<typename T>
void to_json( const std::vector<T>& v, std::ostream& os );
void to_json( const std::string& s,    std::ostream& os ) { os << '"'<<s<<'"';             }
void to_json( const int& i,            std::ostream& os ) { os << i;                       }
void to_json( const double& d,         std::ostream& os ) { os << d;                       }
void to_json( const float& f,          std::ostream& os ) { os << f;                       }
void to_json( const bool& b,           std::ostream& os ) { os << (b ?  "true" : "false"); }

Makes conversion to json of complex types trivial:

struct contact {
    contact( const std::string& f, const std::string& l, int z )
    :first_name(f),last_name(l),zip(z){}

    std::string first_name;
    std::string last_name;
    int         zip;
};

struct address_book {
    std::string name;
    bool        is_locked;
    std::vector<contact> contacts;
};

MACE_REFLECT( contact, (first_name)(last_name)(zip) )
MACE_REFLECT( address_book, (name)(is_locked)(contacts) )

Convert it to JSON:

int main( int argc, char** argv ) {
    address_book ab;  
    ab.name      = "My Address Book";
    ab.is_locked = false;
    ab.contacts.push_back( contact( "Steve", "Jobs", 90210 ) );
    ab.contacts.push_back( contact( "Bill", "Gates", 10000 ) );
    to_json( ab, std::cout );
    return 0;
}

The above code will generate the following output:

{"name":"My Address Book","is_locked":false,"contacts":[{"first_name":"Steve","last_name":"Jobs","zip":90210},{"first_name":"Bill","last_name":"Gates","zip":10000}]}

See the full text for this example in examples/reflect_to_json.cpp

Next Topic: mace_reflect_erasure