codepad
[
create a new paste
]
login
|
about
Language:
C
C++
D
Haskell
Lua
OCaml
PHP
Perl
Plain Text
Python
Ruby
Scheme
Tcl
#include <boost/typeof/typeof.hpp> #include <boost/type_traits/is_same.hpp> #include <iostream> namespace boost { namespace property { class not_implemented {}; ///Dummy class used as base class for property when detecting whether a property has get/set functions template<typename Class> class property_signature { public: Class* self() {return 0;} const Class* self() const {return 0;} not_implemented get() const; void set(not_implemented); }; ///Trait to extract return type and argument type of get/set functions template<typename T> struct property_get_type; template<typename ReturnType,typename Class> struct property_get_type<ReturnType (Class::*)() const> { typedef ReturnType type; }; template<typename ReturnType,typename Class> struct property_get_type<ReturnType (Class::*)()> { typedef ReturnType type; }; template<typename T> struct property_set_type; template<typename ReturnType,typename Class,typename Argument> struct property_set_type<ReturnType (Class::*)(Argument)> { typedef Argument type; }; ///Traits class template<typename Derived,typename Class,typename Signature> class property_traits { private: typedef BOOST_TYPEOF_TPL(&Signature::get) signature_of_get; typedef BOOST_TYPEOF_TPL(&Signature::set) signature_of_set; public: typedef typename property_get_type<signature_of_get>::type get_return_type; typedef typename property_set_type<signature_of_set>::type set_argument_type; typedef boost::mpl::bool_<!boost::is_same<get_return_type,not_implemented>::value> has_get; typedef boost::mpl::bool_<!boost::is_same<set_argument_type,not_implemented>::value> has_set; typedef Derived derived_type; typedef Class class_type; }; template<typename Traits> class property_base { protected: typedef typename Traits::derived_type derived_type; typedef typename Traits::class_type class_type; derived_type& derived() {return *static_cast<derived_type*>(this);} const derived_type& derived() const {return *static_cast<const derived_type*>(this);} public: class_type* self() { size_t offset=derived().offset(); return reinterpret_cast<class_type*>(size_t(this)-offset); } const class_type* self() const { size_t offset=derived().offset(); return reinterpret_cast<class_type*>(size_t(this)-offset); } }; //Enable get-like syntax only when get is implemented. template<typename Traits,typename HasGet,typename Base=property_base<Traits> > class property_get : public Base { public: typedef typename Traits::get_return_type return_type; operator return_type() const {return Base::derived().get();} }; template<typename Traits,typename Base> class property_get<Traits,boost::mpl::false_,Base> : public Base {}; //Enable set-like syntax only when set is implemented. template<typename Traits,typename HasSet,typename Base=property_base<Traits> > class property_set : public Base { public: typedef typename Traits::derived_type derived_type; typedef property_set property_set_type; typedef typename Traits::set_argument_type argument_type; derived_type& operator=(argument_type arg) {Base::derived().set(arg);return Base::derived();} }; template<typename Traits,typename Base> class property_set<Traits,boost::mpl::false_,Base> : public Base { public: typedef property_set property_set_type; }; //Enable functionality of property, such as operator=,operator T(), operator[] etc. template<typename Traits> class property_selector : public property_get<Traits,typename Traits::has_get,property_set<Traits,typename Traits::has_set> > { }; #define BOOST_PROPERTY(Class,Property,Name)\ struct _Property ## Name ## Impl_ : public \ Property<\ boost::property::property_selector<\ boost::property::property_traits<\ _Property ## Name ## Impl_,\ Class,\ Property<boost::property::property_signature<Class> >\ >\ >\ >{\ public:\ /*Extract the position of this member variable relative to the start of (this) for the Class.*/\ size_t offset() const {\ union {\ Class* class_pointer;\ size_t rep;\ } c;\ c.rep=0;\ return size_t(&c.class_pointer->Name);\ }\ using property_set_type::operator=;\ } Name template<typename T> struct has_property_get_impl { static boost::type_traits::no_type has_property_get_tester(...); template<typename A,typename B> static boost::type_traits::yes_type has_property_get_tester(const property_get<A,boost::mpl::true_,B>&); static T make_type(); BOOST_STATIC_CONSTANT(bool,value=sizeof(has_property_get_tester(make_type()))==sizeof(boost::type_traits::yes_type)); }; template<typename T> struct has_property_get : public boost::mpl::bool_<has_property_get_impl<T>::value> {}; template<typename T,typename EnableIf=void> struct result_type { typedef const T& type; }; template<typename T> struct extract_return_type { typedef typename T::return_type type; }; template<typename T> struct result_type<T,typename boost::enable_if<has_property_get<T>,void>::type> { typedef typename extract_return_type<T>::type type; }; template<typename Lhs,typename Rhs> struct typeof_multiply { typedef typename result_type<Lhs>::type lhs_type; typedef typename result_type<Rhs>::type rhs_type; static lhs_type make_lhs(); static rhs_type make_rhs(); typedef BOOST_TYPEOF_TPL(make_lhs()*make_rhs()) type; }; template<typename Lhs,typename Rhs> typename typeof_multiply<Lhs,Rhs>::type operator*(const Lhs& lhs,const Rhs& rhs) { typedef typename result_type<Lhs>::type lhs_type; typedef typename result_type<Rhs>::type rhs_type; return lhs_type(lhs)*rhs_type(rhs); } }} class A { public: virtual ~A() {} public: template<typename Base> class MyProperty : public Base { public: void set(const double& arg) { m_arg=arg; Base::self()->refresh(); } const double& get() const { return m_arg; } private: double m_arg; }; BOOST_PROPERTY(A,MyProperty,X); void refresh() { std::cout << "X Changed to " << X << " square is " << X*X; } }; int main() { A a; a.X=5; }
Private
[
?
]
Run code
Submit