[ create a new paste ] login | about

Link: http://codepad.org/A4vaAMPZ    [ raw code | output | fork ]

burbelgruff - C++, pasted on Oct 20:
#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;
}


Output:
1
X Changed to 5 square is 25


Create a new paste based on this one


Comments: