Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r49581 - in sandbox/introspection: . boost boost/introspection boost/introspection/detail libs libs/introspection libs/introspection/build libs/introspection/msvc libs/introspection/src libs/introspection/test
From: jl_at_[hidden]
Date: 2008-11-03 22:17:37


Author: jll
Date: 2008-11-03 22:17:36 EST (Mon, 03 Nov 2008)
New Revision: 49581
URL: http://svn.boost.org/trac/boost/changeset/49581

Log:
Another proposal for introspection/reflection.
Added:
   sandbox/introspection/
   sandbox/introspection/boost/
   sandbox/introspection/boost/introspection/
   sandbox/introspection/boost/introspection/detail/
   sandbox/introspection/boost/introspection/detail.hpp (contents, props changed)
   sandbox/introspection/boost/introspection/detail/fun_n_spec.hpp (contents, props changed)
   sandbox/introspection/boost/introspection/detail/function_type_helper_spec.hpp (contents, props changed)
   sandbox/introspection/boost/introspection/detail/make_spec.hpp (contents, props changed)
   sandbox/introspection/boost/introspection/introspection.hpp (contents, props changed)
   sandbox/introspection/libs/
   sandbox/introspection/libs/introspection/
   sandbox/introspection/libs/introspection/build/
   sandbox/introspection/libs/introspection/build/Jamfile.v2 (contents, props changed)
   sandbox/introspection/libs/introspection/msvc/
   sandbox/introspection/libs/introspection/msvc/introspection.sln (contents, props changed)
   sandbox/introspection/libs/introspection/msvc/introspection.vcproj (contents, props changed)
   sandbox/introspection/libs/introspection/src/
   sandbox/introspection/libs/introspection/src/class_type.cpp (contents, props changed)
   sandbox/introspection/libs/introspection/test/
   sandbox/introspection/libs/introspection/test/Jamfile.v2 (contents, props changed)
   sandbox/introspection/libs/introspection/test/test.cpp (contents, props changed)

Added: sandbox/introspection/boost/introspection/detail.hpp
==============================================================================
--- (empty file)
+++ sandbox/introspection/boost/introspection/detail.hpp 2008-11-03 22:17:36 EST (Mon, 03 Nov 2008)
@@ -0,0 +1,37 @@
+#include <iostream>
+#include <vector>
+#include <map>
+#include <memory>
+#include <boost/type_traits.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/intrusive_ptr.hpp>
+
+namespace boost { namespace introspection {
+
+namespace detail {
+
+template<typename T>
+class auto_vector_ptr : public std::vector<T*>
+{
+public:
+ ~auto_vector_ptr()
+ {
+ typename std::vector<T*>::reverse_iterator iter(this->rbegin()), last(this->rend());
+ while (iter != last)
+ delete *iter++;
+ }
+};
+
+template<typename K, typename V>
+class auto_map_ptr : public std::map<K, V*>
+{
+public:
+ ~auto_map_ptr()
+ {
+ typename std::map<K, V*>::reverse_iterator iter(this->rbegin()), last(this->rend());
+ while (iter != last)
+ delete iter++->second;
+ }
+};
+
+} } }
\ No newline at end of file

Added: sandbox/introspection/boost/introspection/detail/fun_n_spec.hpp
==============================================================================
--- (empty file)
+++ sandbox/introspection/boost/introspection/detail/fun_n_spec.hpp 2008-11-03 22:17:36 EST (Mon, 03 Nov 2008)
@@ -0,0 +1,74 @@
+#define n BOOST_PP_ITERATION()
+
+template<>
+struct fun_n<n>
+{
+ template<typename FUNCTION_TYPE>
+ class free_fun : public member
+ {
+ public:
+ typedef typename FUNCTION_TYPE::return_type return_type;
+ typedef typename FUNCTION_TYPE::arglist_type arglist_type;
+ typedef return_type (*function_pointer_type)(BOOST_PP_REPEAT(n, BOOST_INTROSPECTION_DISPATCHER_SPECIALIZATION_PARAM, unused));
+
+ free_fun(const std::string& name, function_pointer_type fun) : member(name), fun_(fun) { }
+
+ function_pointer_type function() const { return fun_; }
+
+ private:
+ function_pointer_type fun_;
+ };
+
+ template<typename POINTER_TYPE, typename FUNCTION_TYPE>
+ inline static free_fun<FUNCTION_TYPE>*
+ make_free_fun(const std::string& name, POINTER_TYPE pointer)
+ { return new free_fun<FUNCTION_TYPE>(name, pointer); }
+
+ template<typename CLASS, typename FUNCTION_TYPE>
+ static void* make(BOOST_PP_REPEAT(n, BOOST_INTROSPECTION_DISPATCHER_SPECIALIZATION_PARAM, unused))
+ {
+ CLASS* object(new CLASS(BOOST_PP_ENUM_PARAMS(n, a)));
+ return object;
+ }
+
+ template<typename FUNCTION_TYPE>
+ class mem_fun : public member
+ {
+ public:
+ typedef typename FUNCTION_TYPE::return_type return_type;
+ typedef typename FUNCTION_TYPE::arglist_type arglist_type;
+
+ mem_fun(const std::string& name) : member(name) { }
+
+ virtual return_type
+ call(void* obj BOOST_PP_COMMA_IF(n)
+ BOOST_PP_REPEAT(n, BOOST_INTROSPECTION_DISPATCHER_SPECIALIZATION_PARAM, unused)) const = 0;
+ };
+
+ template<typename CLASS, typename POINTER_TYPE, typename FUNCTION_TYPE>
+ class direct_mem_fun : public mem_fun<FUNCTION_TYPE>
+ {
+ public:
+ direct_mem_fun(const std::string& name, POINTER_TYPE pm)
+ : mem_fun<FUNCTION_TYPE>(name), pm_(pm) { }
+
+ typedef typename FUNCTION_TYPE::return_type return_type;
+ typedef typename FUNCTION_TYPE::arglist_type arglist_type;
+
+ return_type call(void* obj BOOST_PP_COMMA_IF(n)
+ BOOST_PP_REPEAT(n, BOOST_INTROSPECTION_DISPATCHER_SPECIALIZATION_PARAM, unused)) const {
+ return (reinterpret_cast<CLASS*>(obj)->*pm_)(BOOST_PP_ENUM_PARAMS(n, a)); }
+
+ private:
+ POINTER_TYPE pm_;
+ };
+
+ template<typename CLASS, typename POINTER_TYPE, typename FUNCTION_TYPE>
+ inline static direct_mem_fun<CLASS, POINTER_TYPE, FUNCTION_TYPE>*
+ make_direct_mem_fun(const std::string& name, POINTER_TYPE pointer)
+ { return new direct_mem_fun<CLASS, POINTER_TYPE, FUNCTION_TYPE>(name, pointer); }
+
+
+}; // struct fun_n<n>
+
+#undef n

Added: sandbox/introspection/boost/introspection/detail/function_type_helper_spec.hpp
==============================================================================
--- (empty file)
+++ sandbox/introspection/boost/introspection/detail/function_type_helper_spec.hpp 2008-11-03 22:17:36 EST (Mon, 03 Nov 2008)
@@ -0,0 +1,21 @@
+#define n BOOST_PP_ITERATION()
+
+template<typename RETURN, typename CLASS BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename A)>
+struct function_type_helper<RETURN (CLASS::*)(BOOST_PP_ENUM_PARAMS(n, A))>
+{
+ typedef function_type<RETURN, mpl::vector<BOOST_PP_ENUM_PARAMS(n, A)>, mpl::false_> function_type;
+};
+
+template<typename RETURN, typename CLASS BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename A)>
+struct function_type_helper<RETURN (CLASS::*)(BOOST_PP_ENUM_PARAMS(n, A)) const>
+{
+ typedef function_type<RETURN, mpl::vector<BOOST_PP_ENUM_PARAMS(n, A)>, mpl::true_> function_type;
+};
+
+template<typename RETURN BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename A)>
+struct function_type_helper<RETURN (*)(BOOST_PP_ENUM_PARAMS(n, A))>
+{
+ typedef function_type<RETURN, mpl::vector<BOOST_PP_ENUM_PARAMS(n, A)>, mpl::false_> function_type;
+};
+
+#undef n

Added: sandbox/introspection/boost/introspection/detail/make_spec.hpp
==============================================================================
--- (empty file)
+++ sandbox/introspection/boost/introspection/detail/make_spec.hpp 2008-11-03 22:17:36 EST (Mon, 03 Nov 2008)
@@ -0,0 +1,11 @@
+#define n BOOST_PP_ITERATION()
+
+template<BOOST_PP_ENUM_PARAMS(n, typename A)>
+object make(const std::string& class_name, BOOST_PP_ENUM_BINARY_PARAMS(n, A, a))
+{
+ const class_type* type = user_defined_type::by_name<class_type>(class_name);
+ return object(type, type->static_function<
+ typename function_type_helper<void* (*)(BOOST_PP_ENUM_PARAMS(n, A))>::function_type >("")(BOOST_PP_ENUM_PARAMS(n, a)));
+}
+
+#undef n

Added: sandbox/introspection/boost/introspection/introspection.hpp
==============================================================================
--- (empty file)
+++ sandbox/introspection/boost/introspection/introspection.hpp 2008-11-03 22:17:36 EST (Mon, 03 Nov 2008)
@@ -0,0 +1,666 @@
+#ifndef BOOST_INTROSPECTION_HPP
+#define BOOST_INTROSPECTION_HPP
+
+#include <iostream>
+#include <vector>
+#include <map>
+#include <memory>
+#include <stdexcept>
+#include <boost/type_traits.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/introspection/detail.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/at.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/preprocessor/repetition.hpp>
+#include <boost/preprocessor/arithmetic/sub.hpp>
+#include <boost/preprocessor/punctuation/comma_if.hpp>
+#include <boost/preprocessor/iteration/iterate.hpp>
+
+#ifdef _WIN32
+#pragma warning(disable: 4355)
+#endif
+
+namespace boost { namespace introspection {
+
+class member_type_error : public std::runtime_error
+{
+public:
+ member_type_error(const std::string& class_name, const std::string& member_name, const std::type_info& tid) :
+ std::runtime_error("member " + class_name + "::" + member_name + " cannot be converted to " + tid.name()),
+ class_(class_name), member_(member_name), tid_(tid) { }
+
+ virtual ~member_type_error() throw () { }
+
+private:
+ std::string class_, member_;
+ const std::type_info& tid_;
+};
+
+class member_not_found : public std::runtime_error
+{
+public:
+ member_not_found(const std::string& class_name, const std::string& member_name) :
+ std::runtime_error("member " + class_name + "::" + member_name + " not found"),
+ class_(class_name), member_(member_name) { }
+
+ virtual ~member_not_found() throw () { }
+
+private:
+ std::string class_, member_;
+};
+
+class type_not_found : public std::runtime_error
+{
+public:
+ type_not_found(const std::string& name) :
+ std::runtime_error("type " + name + " not found"),
+ class_(name) { }
+
+ virtual ~type_not_found() throw () { }
+
+private:
+ std::string class_;
+};
+
+class ambiguous : public std::runtime_error
+{
+public:
+ ambiguous(const std::string& class_name, const std::string& member_name) :
+ std::runtime_error("member " + class_name + "::" + member_name + " is ambiguous"),
+ class_(class_name), member_(member_name) { }
+
+ virtual ~ambiguous() throw () { }
+
+private:
+ std::string class_, member_;
+};
+
+#define raw_name name
+
+class user_defined_type
+{
+public:
+ user_defined_type(const std::type_info& ti)
+ {
+ id_map()[ti.raw_name()] = this;
+ }
+
+ virtual ~user_defined_type() { }
+
+ template<class T>
+ static const T* by_id(const std::type_info& ti)
+ {
+ return get_typed<T>(ti.raw_name(), id_map());
+ }
+
+ template<class T>
+ static const T* by_name(const std::string& name)
+ {
+ return get_typed<T>(name, name_map());
+ }
+
+ void name(const std::string& n)
+ {
+ name_ = n;
+ name_map()[n] = this;
+ }
+
+ std::string name() const { return name_; }
+
+private:
+
+ std::string name_;
+
+ template<class T>
+ static const T* get_typed(const std::string& name, const std::map<std::string, user_defined_type*>& index)
+ {
+ if (const T* p = dynamic_cast<const T*>(get_untyped(name, index)))
+ return p;
+ else
+ throw type_not_found(name);
+ }
+
+ static const user_defined_type* get_untyped(const std::string& name, const std::map<std::string, user_defined_type*>& index)
+ {
+ std::map<std::string, user_defined_type*>::const_iterator iter(index.find(name));
+ return iter == index.end() ? 0 : iter->second;
+ }
+
+
+ static std::map<std::string, user_defined_type*>& id_map()
+ {
+ static std::map<std::string, user_defined_type*> the_map;
+ return the_map;
+ }
+
+ static std::map<std::string, user_defined_type*>& name_map()
+ {
+ static std::map<std::string, user_defined_type*> the_map;
+ return the_map;
+ }
+};
+
+class class_type;
+class object;
+class const_object;
+
+enum inheritance_flag {
+ public_ = 0, protected_ = 1, private_ = 2, virtual_ = 4,
+ default_inheritance_ = public_
+};
+
+struct direct_base
+{
+ const class_type* class_;
+ int flags_;
+ void* (*upcast_)(void*);
+ bool is_virtual() const { return (flags_ & virtual_) != 0; }
+};
+
+typedef boost::shared_ptr< const std::vector<const direct_base*> > inheritance_path;
+
+class member
+{
+public:
+ member(const std::string& name)
+ : name_(name) { }
+
+ virtual ~member() { }
+
+ const std::string& name() const { return name_; }
+private:
+ std::string name_;
+};
+
+template<int N>
+struct fun_n;
+
+#define BOOST_INTROSPECTION_DISPATCHER_SPECIALIZATION_PARAM(z, n, unused) \
+ BOOST_PP_COMMA_IF(n) typename mpl::at_c<typename FUNCTION_TYPE::arglist_type, n>::type BOOST_PP_CAT(a, n)
+
+#define BOOST_INTROSPECTION_MAX_SIZE BOOST_MPL_LIMIT_VECTOR_SIZE
+#define BOOST_PP_ITERATION_LIMITS (0, BOOST_INTROSPECTION_MAX_SIZE - 1)
+#define BOOST_PP_FILENAME_1 "boost/introspection/detail/fun_n_spec.hpp"
+#include BOOST_PP_ITERATE()
+
+template<typename T>
+class mem_var : public member
+{
+public:
+ mem_var(const std::string& name)
+ : member(name) { }
+
+ virtual void* address(void* object) const = 0;
+ const void* address(const void* object) const { return address(const_cast<void*>(object)); }
+};
+
+template<class C, typename T>
+class direct_mem_var : public mem_var<T>
+{
+public:
+ direct_mem_var(const std::string& name, T (C::*pointer))
+ : mem_var<T>(name), pointer_(pointer) { }
+
+ virtual void* address(void* object) const
+ {
+ return &(reinterpret_cast<C*>(object)->*pointer_);
+ }
+
+private:
+ T (C::*pointer_);
+};
+
+struct base
+{
+ base() : refs_(0) { }
+ int refs_;
+ const class_type* class_;
+ bool virtual_;
+ inheritance_path path_;
+ std::vector< boost::intrusive_ptr<base> > bases_;
+};
+
+inline void intrusive_ptr_add_ref(base* p)
+{
+ ++p->refs_;
+}
+
+inline void intrusive_ptr_release(base* p)
+{
+ if (--p->refs_ == 0)
+ delete p;
+}
+
+template<class MEMBER_CLASS>
+class qualified_member
+{
+public:
+ qualified_member(const MEMBER_CLASS* member) : path_(new std::vector<const class_type*>), member_(member) { }
+ qualified_member(inheritance_path path, const MEMBER_CLASS* member) : path_(path), member_(member) { }
+
+ inheritance_path path() const { return path_; }
+ const MEMBER_CLASS* direct_member() const { return member_; }
+
+private:
+ inheritance_path path_;
+ const MEMBER_CLASS* member_;
+};
+
+typedef std::vector< qualified_member<member> > qualified_member_vector;
+
+template<typename RETURN, typename ARGLIST, typename IS_CONST>
+struct function_type
+{
+ typedef RETURN return_type;
+ typedef ARGLIST arglist_type;
+ typedef IS_CONST const_type;
+ enum { arglist_size = mpl::size<arglist_type>::value };
+ typedef fun_n<arglist_size> fun_n_type;
+ typedef typename fun_n_type::template free_fun<function_type> free_fun_type;
+ typedef typename fun_n_type::template mem_fun<function_type> mem_fun_type;
+ typedef qualified_member< typename fun_n_type::template mem_fun<function_type> > qualified_member_type;
+};
+
+template<typename T>
+struct function_type_helper;
+
+#define BOOST_PP_ITERATION_LIMITS (0, BOOST_INTROSPECTION_MAX_SIZE - 1)
+#define BOOST_PP_FILENAME_1 "boost/introspection/detail/function_type_helper_spec.hpp"
+#include BOOST_PP_ITERATE()
+
+template<typename T>
+struct member_function : public function_type_helper<T>::function_type::qualified_member_type
+{
+ typedef typename function_type_helper<T>::function_type function_type;
+ typedef typename function_type::return_type return_type;
+ typedef typename function_type::arglist_type arglist_type;
+ typedef typename function_type::const_type const_type;
+ typedef typename function_type::qualified_member_type qualified_member_type;
+
+ member_function(object& o, const std::string& name);
+ member_function(const const_object& o, const std::string& name);
+};
+
+class class_type : public user_defined_type
+{
+public:
+ class_type(const std::type_info& ti) : user_defined_type(ti), collect_qualified_members_done_(false) { }
+
+ void add(member* pm)
+ {
+ std::auto_ptr<member> track(pm);
+ direct_members_.reserve(direct_members_.size() + 1);
+ direct_member_map_[pm->name()] = pm;
+ direct_members_.push_back(pm);
+ track.release();
+ }
+
+ const qualified_member_vector& candidates(const std::string& member_name) const;
+
+ template<typename T>
+ qualified_member< mem_var<T> > member_variable(const std::string& var_name) const
+ {
+ const qualified_member_vector& vars(candidates(var_name));
+
+ if (vars.size() > 1)
+ throw ambiguous(name(), var_name);
+
+ const mem_var<T>* pm(dynamic_cast<const mem_var<T>*>(vars.front().direct_member()));
+
+ if (!pm)
+ throw member_type_error(name(), var_name, typeid(T));
+
+ return qualified_member< mem_var<T> >(vars.front().path(), pm);
+ }
+
+ template<typename FUNCTION_TYPE>
+ typename FUNCTION_TYPE::qualified_member_type
+ member_function(const std::string& function_name) const
+ {
+ const qualified_member_vector& functions(candidates(function_name));
+
+ qualified_member_vector::const_iterator iter(functions.begin()), last(functions.end());
+
+ typedef typename FUNCTION_TYPE::mem_fun_type mem_fun_type;
+
+ while (iter != last)
+ {
+ if (const mem_fun_type* pm = dynamic_cast<const mem_fun_type*>(iter->direct_member()))
+ return typename FUNCTION_TYPE::qualified_member_type(iter->path(), pm);
+
+ ++iter;
+ }
+
+ throw member_not_found(name(), function_name);
+ }
+
+ template<typename FUNCTION_TYPE>
+ typename FUNCTION_TYPE::free_fun_type::function_pointer_type
+ static_function(const std::string& function_name) const
+ {
+ const qualified_member_vector& functions(candidates(function_name));
+ qualified_member_vector::const_iterator iter(functions.begin()), last(functions.end());
+ typedef typename FUNCTION_TYPE::free_fun_type free_fun_type;
+
+ while (iter != last)
+ {
+ if (const free_fun_type* fun = dynamic_cast<const free_fun_type*>(iter->direct_member()))
+ return fun->function();
+
+ ++iter;
+ }
+
+ throw member_not_found(name(), function_name);
+ }
+
+ void* adjust(const inheritance_path& path, void* address) const;
+
+ const void* adjust(const inheritance_path& path, const void* address) const
+ { return adjust(path, const_cast<void*>(address)); }
+
+ void dump_inheritance_graph(std::ostream& os) const;
+ void dump_inheritance_tree(std::ostream& os) const;
+
+private:
+
+ void build_inheritance_graph() const;
+ void build_inheritance_graph(class_type* complete_class, std::vector< boost::intrusive_ptr<base> > & bases,
+ std::vector<const direct_base*>& path, std::map<const class_type*, boost::intrusive_ptr<base> >& virtual_bases) const;
+ static void dump_inheritance_tree(std::ostream& os, int indent, const std::vector< intrusive_ptr<base> >& bases);
+ static void dump_inheritance_graph_bases(std::ostream& os, const std::vector< intrusive_ptr<base> >& bases);
+
+ void collect_qualified_members() const;
+
+ detail::auto_vector_ptr<direct_base> direct_bases_;
+ detail::auto_vector_ptr<member> direct_members_;
+ std::map<std::string, member*> direct_member_map_;
+ mutable std::vector< boost::intrusive_ptr<base> > bases_;
+ mutable std::vector< qualified_member<member> > qualified_members_;
+ mutable std::map<std::string, std::vector< qualified_member<member> > > qualified_member_map_;
+ mutable bool collect_qualified_members_done_;
+
+ template<class C> friend class introspection_class;
+};
+
+class value
+{
+};
+
+template<typename T>
+struct member_variable;
+
+template<typename T>
+struct member_function;
+
+template<typename OBJECT, typename FUNCTION>
+struct bound_member_function;
+
+class object : public value
+{
+public:
+ template<class T>
+ object(T* static_pointer)
+ : address_(static_pointer), class_(user_defined_type::by_id<class_type>(typeid(T))) { }
+
+ object(const class_type* cls, void* address)
+ : class_(cls), address_(address) { }
+
+ object(const std::string& class_name)
+ : class_(user_defined_type::by_name<class_type>(class_name)),
+ address_(class_->static_function< function_type_helper<void* (*)()>::function_type >("")()) { }
+
+ object(const char* class_name)
+ : class_(user_defined_type::by_name<class_type>(class_name)),
+ address_(class_->static_function< function_type_helper<void* (*)()>::function_type >("")()) { }
+
+ template<typename T>
+ T& operator [](const member_variable<T>& var);
+
+ template<typename T>
+ bound_member_function< object, member_function<T> > operator [](const member_function<T>& fun);
+
+ template<typename T>
+ bound_member_function< object, member_function<T> > function(const std::string& name);
+
+ const class_type* type() const { return class_; }
+ void* address() const { return address_; }
+
+private:
+ const class_type* class_;
+ void* address_;
+};
+
+class const_object
+{
+public:
+ template<class T>
+ const_object(const T* static_pointer)
+ : address_(static_pointer), class_(user_defined_type::by_id<class_type>(typeid(T))) { }
+
+ const_object(const class_type* cls, void* address) : class_(cls), address_(address) { }
+
+ const_object(const object& obj) : class_(obj.type()), address_(obj.address()) { }
+
+ template<typename T>
+ const T& operator [](const member_variable<T>& var) const;
+
+ template<typename T>
+ typename enable_if<
+ typename member_function<T>::const_type,
+ bound_member_function< const_object, member_function<T> >
+ >::type
+ operator [](const member_function<T>& fun) const;
+
+ template<typename T>
+ typename enable_if<
+ typename member_function<T>::const_type,
+ bound_member_function< const_object, member_function<T> >
+ >::type
+ function(const std::string& name) const;
+
+ const class_type* type() const { return class_; }
+
+ const void* address() const { return address_; }
+
+private:
+ void* address_;
+ const class_type* class_;
+ bool is_const;
+};
+
+template<typename T>
+member_function<T>::member_function(object& o, const std::string& name)
+ : qualified_member_type(o.type()->class_type::member_function<typename function_type_helper<T>::function_type>(name)) { }
+
+template<typename T>
+member_function<T>::member_function(const const_object& o, const std::string& name)
+ : qualified_member_type(o.type()->class_type::member_function<function_type>(name)) { }
+
+template<typename T>
+struct member_variable : public qualified_member< mem_var<T> >
+{
+ member_variable(object& o, const std::string& name)
+ : qualified_member< mem_var<T> >(o.type()->class_type::member_variable<T>(name)) { }
+
+ member_variable(const_object& o, const std::string& name)
+ : qualified_member< mem_var<T> >(o.type()->class_type::member_variable<T>(name)) { }
+};
+
+template<typename T>
+T& object::operator [](const member_variable<T>& var)
+{
+ return *reinterpret_cast<T*>(var.direct_member()->address(class_->adjust(var.path(), address_)));
+}
+
+template<typename T>
+const T& const_object::operator [](const member_variable<T>& var) const
+{
+ return *reinterpret_cast<T*>(var.direct_member()->address(class_->adjust(var.path(), address_)));
+}
+
+template<typename OBJECT, typename FUNCTION>
+struct bound_member_function
+{
+ typedef typename FUNCTION::function_type::return_type return_type;
+
+ bound_member_function(const OBJECT* po, FUNCTION member_function) : object_(po), function_(member_function) { }
+
+ const OBJECT* object_;
+ FUNCTION function_;
+
+ return_type operator ()() const
+ {
+ return function_.direct_member()->call(
+ object_->type()->adjust(function_.path(), const_cast<void*>(object_->address())));
+ }
+};
+
+template<typename T>
+bound_member_function< object, member_function<T> > object::operator [](const member_function<T>& fun)
+{
+ return bound_member_function<object, member_function<T> >(this, fun);
+}
+
+template<typename T>
+bound_member_function< object, member_function<T> > object::function(const std::string& name)
+{
+ return (*this)[member_function<T>(*this, name)];
+}
+
+template<typename T>
+typename enable_if<
+ typename member_function<T>::const_type,
+ bound_member_function< const_object, member_function<T> >
+>::type
+const_object::operator [](const member_function<T>& fun) const
+{
+ return bound_member_function< const_object, member_function<T> >(this, fun);
+}
+
+template<typename T>
+typename enable_if<
+ typename member_function<T>::const_type,
+ bound_member_function< const_object, member_function<T> >
+>::type
+const_object::function(const std::string& name) const
+{
+ return (*this)[member_function<T>(*this, name)];
+}
+
+template<class T>
+object downcast(const T* static_pointer)
+{
+ return const_object(
+ user_defined_type::by_id<class_type>(typeid(*static_pointer)),
+ introspection_class<typename boost::remove_cv<T>::type>::base_address(static_pointer));
+}
+
+template<class T>
+object downcast(T* static_pointer)
+{
+ return object(
+ user_defined_type::by_id<class_type>(typeid(*static_pointer)),
+ introspection_class<typename boost::remove_cv<T>::type>::base_address(static_pointer));
+}
+
+// =========================================================
+
+template<class C>
+class introspection_class
+{
+ public:
+
+ static class_type* instance()
+ {
+ static class_type cl(typeid(C));
+ return &cl;
+ }
+
+ static typename enable_if<is_polymorphic<C>, void*>::type base_address(C* obj)
+ {
+ return dynamic_cast<void*>(obj);
+ }
+
+ static const void* base_address(const C* obj)
+ {
+ return base_address(const_cast<C*>(obj), is_polymorphic<C>::type());
+ }
+
+ static void name(const std::string& name)
+ {
+ instance()->name(name);
+ }
+
+ template<typename T>
+ static void variable(const std::string& name, T (C::*pointer))
+ {
+ instance()->add(new direct_mem_var<C, T>(name, pointer));
+ }
+
+ template<typename T>
+ static void function(const std::string& name, T pointer)
+ {
+ typedef typename function_type_helper<T>::function_type function_type;
+ instance()->add(function_type::fun_n_type::
+ template make_direct_mem_fun<C, T, function_type>(name, pointer));
+ }
+
+ template<typename T>
+ static void constructor()
+ {
+ typedef typename function_type_helper<T>::function_type function_type;
+ typedef typename function_type::fun_n_type fun_n_type;
+ instance()->add(fun_n_type::template make_free_fun<T, function_type>("", fun_n_type::template make<C, function_type>));
+ }
+
+ template<typename B>
+ static void base(inheritance_flag flag1 = default_inheritance_, inheritance_flag flag2 = default_inheritance_)
+ {
+ std::auto_ptr<direct_base> base(new direct_base);
+ base->class_ = introspection_class<B>::instance();
+ base->flags_ = static_cast<int>(flag1) | static_cast<int>(flag2);
+ struct local { static void* upcast(void* p) { return static_cast<B*>(reinterpret_cast<C*>(p)); } };
+ base->upcast_ = local::upcast;
+ instance()->direct_bases_.push_back(base.get());
+ direct_base* p = instance()->direct_bases_.front();
+ base.release();
+ }
+};
+
+#define BOOST_INTROSPECTION_MAX_SIZE BOOST_MPL_LIMIT_VECTOR_SIZE
+#define BOOST_PP_ITERATION_LIMITS (1, BOOST_INTROSPECTION_MAX_SIZE - 1)
+#define BOOST_PP_FILENAME_1 "boost/introspection/detail/make_spec.hpp"
+#include BOOST_PP_ITERATE()
+
+} }
+
+// =========================================================
+
+#define BOOST_INTROSPECTION_CLASS(_cls) \
+ introspection_class<_cls>::name(#_cls)
+
+#define BOOST_INTROSPECTION_BASE(_cls, _base) \
+ introspection_class<_cls>::base<_base>()
+
+#define BOOST_INTROSPECTION_VIRTUAL_BASE(_cls, _base) \
+ introspection_class<_cls>::base<_base>(virtual_);
+
+#define BOOST_INTROSPECTION_DEFAULT_CONSTRUCTOR(_cls) \
+ introspection_class<_cls>::constructor<void* (*)()>();
+
+#define BOOST_INTROSPECTION_CONSTRUCTOR_1(_cls, _type1) \
+ introspection_class<_cls>::constructor<void* (*)(_type1)>();
+
+#define BOOST_INTROSPECTION_MEMBER_VARIABLE(cls, name) \
+ introspection_class<cls>::variable(#name, &cls::name)
+
+#define BOOST_INTROSPECTION_MEMBER_FUNCTION(cls, name) \
+ introspection_class<cls>::function(#name, &cls::name)
+
+#define BOOST_INTROSPECTION_OVERLOADED_MEMBER_FUNCTION(_cls, _name, _type) \
+ introspection_class<_cls>::function<_type>(#_name, &_cls::_name)
+
+#endif // BOOST_INTROSPECTION_HPP

Added: sandbox/introspection/libs/introspection/build/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/introspection/libs/introspection/build/Jamfile.v2 2008-11-03 22:17:36 EST (Mon, 03 Nov 2008)
@@ -0,0 +1,26 @@
+
+# Boost Introspection Library Build Jamfile
+
+# (C) Jean-Louis Leroy 2008.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or www.boost.org/LICENSE_1_0.txt)
+
+
+# See library home page at http://www.boost.org/libs/introspection
+
+project boost/introspection
+ : source-location ../src
+ ;
+
+SOURCES =
+ class_type ;
+
+lib boost_introspection
+ :
+ $(SOURCES).cpp
+ :
+ :
+ :
+ ;
+
+boost-install boost_introspection ;
\ No newline at end of file

Added: sandbox/introspection/libs/introspection/msvc/introspection.sln
==============================================================================
--- (empty file)
+++ sandbox/introspection/libs/introspection/msvc/introspection.sln 2008-11-03 22:17:36 EST (Mon, 03 Nov 2008)
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual C++ Express 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "introspection", "introspection.vcproj", "{B9AED528-A739-4236-8FBF-E8970EEB4BD1}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B9AED528-A739-4236-8FBF-E8970EEB4BD1}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B9AED528-A739-4236-8FBF-E8970EEB4BD1}.Debug|Win32.Build.0 = Debug|Win32
+ {B9AED528-A739-4236-8FBF-E8970EEB4BD1}.Release|Win32.ActiveCfg = Release|Win32
+ {B9AED528-A739-4236-8FBF-E8970EEB4BD1}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal

Added: sandbox/introspection/libs/introspection/msvc/introspection.vcproj
==============================================================================
--- (empty file)
+++ sandbox/introspection/libs/introspection/msvc/introspection.vcproj 2008-11-03 22:17:36 EST (Mon, 03 Nov 2008)
@@ -0,0 +1,203 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="test"
+ ProjectGUID="{B9AED528-A739-4236-8FBF-E8970EEB4BD1}"
+ RootNamespace="introspection"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\.."
+ PreprocessorDefinitions="_SCL_SECURE_NO_WARNINGS"
+ MinimalRebuild="true"
+ ExceptionHandling="2"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="..\..\.."
+ PreprocessorDefinitions="_SCL_SECURE_NO_WARNINGS"
+ ExceptionHandling="2"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\src\class_type.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\boost\introspection\detail\fun_n_spec.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\boost\introspection\detail\function_type_helper_spec.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\build\Jamfile.v2"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\boost\introspection\detail\make_spec.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\boost\introspection\introspection.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\test\test.cpp"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>

Added: sandbox/introspection/libs/introspection/src/class_type.cpp
==============================================================================
--- (empty file)
+++ sandbox/introspection/libs/introspection/src/class_type.cpp 2008-11-03 22:17:36 EST (Mon, 03 Nov 2008)
@@ -0,0 +1,187 @@
+#include <boost/introspection/introspection.hpp>
+
+namespace boost { namespace introspection {
+
+using namespace std;
+using namespace boost;
+
+const std::vector< qualified_member<member> >&
+class_type::candidates(const std::string& member_name) const
+{
+ build_inheritance_graph();
+
+ map<std::string, vector< qualified_member<member> > >::iterator iter(qualified_member_map_.find(member_name));
+
+ if (iter == qualified_member_map_.end())
+ throw member_not_found(name(), member_name);
+
+ vector< qualified_member<member> >& candidates(iter->second);
+
+ if (candidates.size() == 1)
+ return candidates;
+
+ for (int candidate_index = 0; candidate_index < (int) candidates.size(); ++candidate_index)
+ {
+ qualified_member<member> candidate(candidates[candidate_index]); // don't take ref into vector because it may shrink
+
+ for (int shadow_index = 0; shadow_index < (int) candidates.size(); )
+ {
+ qualified_member<member>& shadow(candidates[shadow_index]);
+
+ if (candidate.path()->size() < shadow.path()->size()
+ && mismatch(candidate.path()->begin(), candidate.path()->end(), shadow.path()->begin()).first == candidate.path()->end())
+ {
+ candidates.erase(candidates.begin() + shadow_index);
+
+ if (candidate_index > shadow_index)
+ --candidate_index;
+ }
+ else
+ {
+ ++shadow_index;
+ }
+ }
+ }
+
+ return candidates;
+}
+
+void class_type::dump_inheritance_graph(std::ostream& os) const
+{
+ build_inheritance_graph();
+ os << name();
+ dump_inheritance_graph_bases(os, bases_);
+}
+
+void class_type::dump_inheritance_graph_bases(std::ostream& os, const vector< intrusive_ptr<base> >& bases)
+{
+ os << '(';
+
+ const char* sep = "";
+ vector< intrusive_ptr<base> >::const_iterator base_iter(bases.begin()), base_last(bases.end());
+
+ while (base_iter != base_last)
+ {
+ os << sep;
+ sep = ",";
+
+ if ((*base_iter)->virtual_)
+ os << '*';
+
+ os << (*base_iter)->class_->name();
+
+ dump_inheritance_graph_bases(os, (*base_iter)->bases_);
+
+ ++base_iter;
+ }
+
+ os << ')';
+}
+
+void class_type::dump_inheritance_tree(std::ostream& os) const
+{
+ build_inheritance_graph();
+ os << name() << endl;
+ dump_inheritance_tree(os, 1, bases_);
+}
+
+void class_type::dump_inheritance_tree(std::ostream& os, int indent, const vector< intrusive_ptr<base> >& bases)
+{
+ vector< intrusive_ptr<base> >::const_iterator base_iter(bases.begin()), base_last(bases.end());
+
+ while (base_iter != base_last)
+ {
+ for (int i = 0; i < indent; i++)
+ os << " ";
+
+ if ((*base_iter)->virtual_)
+ os << "virtual ";
+
+ os << (*base_iter)->class_->name() << endl;
+
+ dump_inheritance_tree(os, indent + 1, (*base_iter)->bases_);
+
+ ++base_iter;
+ }
+}
+
+void class_type::build_inheritance_graph() const
+{
+ if (!collect_qualified_members_done_)
+ {
+ class_type* myself(const_cast<class_type*>(this));
+ std::vector<const direct_base*> path;
+ map<const class_type*, intrusive_ptr<base> > virtual_bases;
+ build_inheritance_graph(myself, myself->bases_, path, virtual_bases);
+ collect_qualified_members_done_ = true;
+ }
+}
+
+void class_type::build_inheritance_graph(class_type* complete_class, vector< intrusive_ptr<base> >& bases,
+ vector<const direct_base*>& path, map<const class_type*, intrusive_ptr<base> >& virtual_bases) const
+{
+ inheritance_path this_path(new vector<const direct_base*>(path));
+
+ vector<member*>::const_iterator member_iter(direct_members_.begin()), member_last(direct_members_.end());
+
+ while (member_iter != member_last)
+ {
+ complete_class->qualified_members_.push_back(qualified_member<member>(this_path, *member_iter));
+ complete_class->qualified_member_map_[(*member_iter)->name()].push_back(qualified_member<member>(this_path, *member_iter));
+ ++member_iter;
+ }
+
+ vector<direct_base*>::const_iterator base_iter(direct_bases_.begin()), base_last(direct_bases_.end());
+
+ while (base_iter != base_last)
+ {
+ const direct_base* direct(*base_iter);
+ path.push_back(direct);
+
+ intrusive_ptr<base> new_base;
+
+ if (direct->is_virtual())
+ {
+ intrusive_ptr<base>& vbase = virtual_bases[direct->class_];
+
+ if (vbase)
+ {
+ bases.push_back(vbase);
+ }
+ else
+ {
+ new_base = new base;
+ new_base->virtual_ = true;
+ vbase = new_base;
+ }
+ }
+ else
+ {
+ new_base = new base;
+ new_base->virtual_ = false;
+ }
+
+ if (new_base)
+ {
+ new_base->class_ = direct->class_;
+ new_base->path_ = inheritance_path(new vector<const direct_base*>(path));
+ direct->class_->build_inheritance_graph(complete_class, new_base->bases_, path, virtual_bases);
+ bases.push_back(new_base);
+ }
+
+ path.pop_back();
+ ++base_iter;
+ }
+}
+
+void* class_type::adjust(const inheritance_path& path, void* address) const
+{
+ std::vector<const direct_base*>::const_iterator iter(path->begin()), last(path->end());
+
+ while (iter != last)
+ address = (*iter++)->upcast_(address);
+
+ return address;
+}
+
+} }

Added: sandbox/introspection/libs/introspection/test/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/introspection/libs/introspection/test/Jamfile.v2 2008-11-03 22:17:36 EST (Mon, 03 Nov 2008)
@@ -0,0 +1,24 @@
+# Boost introspection Library test Jamfile
+
+# (C) Copyright Jean-Louis Leroy 2008.
+# Use, modification, and distribution are subject to the
+# Boost Software License, Version 1.0. (See accompanying file
+# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#
+
+# bring in rules for testing
+import testing ;
+
+project
+ : requirements
+ <library>../build//boost_introspection
+ <link>static
+ <variant>debug
+ ;
+{
+ test-suite "introspection"
+ :
+ [ run test.cpp ]
+ ;
+}
+

Added: sandbox/introspection/libs/introspection/test/test.cpp
==============================================================================
--- (empty file)
+++ sandbox/introspection/libs/introspection/test/test.cpp 2008-11-03 22:17:36 EST (Mon, 03 Nov 2008)
@@ -0,0 +1,201 @@
+#include <iostream>
+#include <boost/test/minimal.hpp>
+#include <boost/introspection/introspection.hpp>
+
+class animal
+{
+public:
+ animal() : age(1), shadow(1000) { }
+ virtual ~animal() { }
+ const animal* animal_part() const { return this; }
+//private:
+ int age;
+ int shadow;
+};
+
+class mammal : public virtual animal
+{
+public:
+ mammal() : teats(2), ambiguous(1001), shadow(1002) { }
+ int teats;
+ int ambiguous;
+ int shadow;
+ const mammal* mammal_part() const { return this; }
+private:
+};
+
+class carnivore : public virtual animal
+{
+public:
+ carnivore() : victims(17), ambiguous(1003) { }
+ int victims;
+ int ambiguous;
+ const carnivore* carnivore_part() const { return this; }
+private:
+};
+
+class dog : public mammal, public carnivore
+{
+public:
+ dog() : name_("Droopy") { }
+ dog(const std::string& name) : name_(name) { }
+ std::string name_;
+ const dog* dog_part() const { return this; }
+ std::string name() const { return name_; }
+ void name(const std::string& n) { name_ = n; }
+ std::string bark() { return "bow wow wow"; }
+};
+
+// =========================================================
+
+using namespace std;
+using namespace boost::introspection;
+
+#ifdef _WIN32
+
+#include <windows.h>
+#include <boost/iostreams/stream.hpp>
+
+using namespace boost::iostreams;
+
+class debug_output_sink : public boost::iostreams::sink {
+public:
+ debug_output_sink(int) { }
+ std::streamsize write(const char* s, std::streamsize n);
+};
+
+streamsize debug_output_sink::write(const char* s, streamsize n)
+{
+ TCHAR chunk[1000 + 1];
+ streamsize remain(n);
+
+ while (remain)
+ {
+ streamsize chunk_size(min(remain, sizeof chunk - 1));
+ *copy(s, s + chunk_size, chunk) = 0;
+ OutputDebugString(chunk);
+ remain -= chunk_size;
+ }
+
+ return n;
+}
+
+#endif
+
+int test_main( int, char *[] )
+{
+#ifdef _WIN32
+ static stream_buffer<debug_output_sink> buf(0);
+ cout.rdbuf(&buf);
+#endif
+
+ introspection_class<animal>::name("animal");
+ introspection_class<animal>::variable("age", &animal::age);
+ introspection_class<animal>::variable("shadow", &animal::shadow);
+ introspection_class<animal>::function<const animal* (animal::*)(void) const>("animal_part", &animal::animal_part);
+
+ BOOST_INTROSPECTION_CLASS(mammal);
+ introspection_class<mammal>::base<animal>(virtual_);
+ BOOST_INTROSPECTION_MEMBER_VARIABLE(mammal, teats);
+ BOOST_INTROSPECTION_MEMBER_VARIABLE(mammal, ambiguous);
+ BOOST_INTROSPECTION_MEMBER_VARIABLE(mammal, shadow);
+
+ BOOST_INTROSPECTION_CLASS(carnivore);
+ BOOST_INTROSPECTION_VIRTUAL_BASE(carnivore, animal);
+ BOOST_INTROSPECTION_MEMBER_VARIABLE(carnivore, victims);
+ BOOST_INTROSPECTION_MEMBER_VARIABLE(carnivore, ambiguous);
+
+ BOOST_INTROSPECTION_CLASS(dog);
+ BOOST_INTROSPECTION_BASE(dog, mammal);
+ BOOST_INTROSPECTION_BASE(dog, carnivore);
+ BOOST_INTROSPECTION_DEFAULT_CONSTRUCTOR(dog);
+ BOOST_INTROSPECTION_CONSTRUCTOR_1(dog, const std::string&);
+ BOOST_INTROSPECTION_MEMBER_VARIABLE(dog, name_);
+ //BOOST_INTROSPECTION_OVERLOADED_MEMBER_FUNCTION(dog, name, (string (dog::*)() const));
+ introspection_class<dog>::function<string (dog::*)() const>("name", &dog::name);
+ introspection_class<dog>::function<void (dog::*)(const string&)>("name", &dog::name);
+ BOOST_INTROSPECTION_MEMBER_FUNCTION(dog, bark);
+
+ introspection_class<dog>::instance()->dump_inheritance_tree(cout);
+
+ {
+ ostringstream opath;
+ introspection_class<dog>::instance()->dump_inheritance_graph(opath);
+ string path(opath.str());
+ cout << path << endl;
+ BOOST_CHECK(path == "dog(mammal(*animal()),carnivore(*animal()))");
+ }
+
+ dog droopy;
+
+ {
+ const_object o(downcast(&droopy));
+
+ member_variable<string> dog_name_(o, "name_");
+ cout << o[dog_name_] << endl;
+ BOOST_CHECK(&o[dog_name_] == &droopy.name_);
+ BOOST_CHECK(o[dog_name_] == droopy.name_);
+
+ member_variable<int> dog_age(o, "age");
+ cout << o[dog_age] << endl;
+ BOOST_CHECK(&droopy.age == &o[dog_age]);
+
+ member_variable<int> dog_teats(o, "teats");
+ cout << o[dog_teats] << endl;
+ BOOST_CHECK(&droopy.teats == &o[dog_teats]);
+
+ member_variable<int> dog_victims(o, "victims");
+ cout << o[dog_victims] << endl;
+ BOOST_CHECK(&droopy.victims == &o[dog_victims]);
+
+ member_variable<int> dog_shadow(o, "shadow");
+ BOOST_CHECK(&droopy.shadow == &o[dog_shadow]);
+
+ try
+ {
+ member_variable<int> ambiguous(o, "ambiguous");
+ BOOST_ERROR("ambiguity not detected");
+ }
+ catch (ambiguous)
+ {
+ }
+ catch (...)
+ {
+ BOOST_ERROR("wrong exception during ambiguity");
+ }
+
+ member_function<string (object::*)() const> dog_name(o, "name");
+ BOOST_CHECK(droopy.name() == o[dog_name]());
+
+ BOOST_CHECK(droopy.animal_part() == o.function<const animal* (object::*)() const>("animal_part")());
+ }
+
+ {
+ object o(downcast(&droopy));
+
+ member_function<string (object::*)()> dog_bark(o, "bark");
+ BOOST_CHECK(droopy.bark() == o[dog_bark]());
+
+ // Can we call const member functions on non-const objects too?
+ member_function<string (object::*)() const> dog_name(o, "name");
+ BOOST_CHECK(droopy.name() == o[dog_name]());
+
+ BOOST_CHECK(droopy.animal_part() == o.function<const animal* (object::*)() const>("animal_part")());
+ }
+
+ {
+ object o("dog");
+ member_function<string (object::*)() const> dog_name(o, "name");
+ BOOST_CHECK(droopy.name() == o[dog_name]());
+ }
+
+ {
+ object o(make<const std::string&>("dog", "Rantanplan"));
+ member_function<string (object::*)() const> dog_name(o, "name");
+ BOOST_CHECK("Rantanplan" == o[dog_name]());
+ }
+
+ cout << flush;
+
+ return 0;
+}


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk