Boost logo

Boost :

Subject: [boost] Another implementation of properties.
From: Germán Diago (germandiago_at_[hidden])
Date: 2010-03-03 11:33:12


Hello. I've been trying to implement properties for c++0x, for now.
I've come up with this solution for now.

You need g++ svn to test it. It's a partial implementation, since not
every operator is overloaded.

Space overhead:

    - one pointer to the object per property instance.
    - the pointer to the member functions is shared among every
instance of the class, so it's a per-class and not per-instance
      overhead, which is negligible.

Usage:

class Person {

       int getAge() const { .... };
       void setAge(int age) { ... };

       PROPS_RWPROPERTY(Age);

       Person() : Age(this) {}
};

You can:
    - declare getters/setters const or nonconst.
    - getters must have one parameter.
    - setters must return void.
    - it has some operators overloaded, but the idea is to overload
all of them if the implementation is all right.

   - the property returns whatever you put in your getter and gets as
a parameter what you put in the setter.

If you declare the getters and setters to be VIRTUAL, you get virtual
behaviour, so you can use virtual properties, even with pure
virtual functions, and it will work.

Caveats:
   - Needs c++0x compiler for now.
    - Not enforced the read-only access for properties for now. I need
extended friend declarations for that, and the operator= would be made
private with friend class. But for now it's not reinforced.

I think this implementation is pretty usable as-is. It's just a matter
of extending it. I don't use the offset trick because I think it does
not work
with classes with virtual members, but I'm not sure.

The implementation contains Trivial properties as well, which for now,
are the same as fields I think.

Implementation:

#include <functional>
#include <type_traits>
#include <iostream>

#ifndef _PROPS_PROPERTY_HPP_
#define _PROPS_PROPERTY_HPP_

namespace props {

template <class GetterAddress, class SetterAddress>
class RWProperty;

template <class GetterAddress, class SetterAddress>
class ROProperty;

template <class PropType>
class TROProperty;

template <class PropType>
class TRWProperty;

namespace detail {

struct unused {};

template <bool cond, class T = void>
struct EnableIf { typedef T type; };

template <class T>
struct EnableIf<false, T> {};

template <bool cond, class T = void>
struct DisableIf {};

template <class T>
struct DisableIf<false, T>
{
    typedef T type;
};

template <class ObjectType, class Ret, Ret (ObjectType::*Getter)()>
struct WrapperGetter {
    typedef ObjectType object_t;

    typedef Ret result_type;

    Ret (ObjectType::*getter)();

    WrapperGetter() : getter(Getter) {}
};

template <class ObjectType, class Ret, Ret (ObjectType::*Getter)() const>
struct WrapperGetterConst {
    typedef ObjectType object_t;

    typedef Ret result_type;

    Ret (ObjectType::*getter)() const;

    WrapperGetterConst() : getter(Getter) {}
};

template <class ObjectType, class Arg, void (ObjectType::*Setter)(Arg)>
struct WrapperSetter {
    typedef ObjectType object_t;
    typedef void result_type;
    typedef Arg argument_type;

    void (ObjectType::*setter)(Arg);

    WrapperSetter() : setter(Setter) {}
};

template <class ObjectType, class Arg, void (ObjectType::*Setter)(Arg) const>
struct WrapperSetterConst {
    typedef ObjectType object_t;
    typedef void result_type;
    typedef Arg argument_type;

    void (ObjectType::*setter)(Arg) const;

    WrapperSetterConst() : setter(Setter) {}
};

template <class T>
struct IsProperty : public std::false_type {};

template <class GetterAddress, class SetterAddress>
struct IsProperty<RWProperty<GetterAddress, SetterAddress> > :
public std::true_type {};

template <class GetterAddress, class SetterAddress>
struct IsProperty<ROProperty<GetterAddress, SetterAddress> > :
public std::true_type {};

template <class PropType>
struct IsProperty<TRWProperty<PropType> > : public std::true_type {};

template <class PropType>
struct IsProperty<TROProperty<PropType> > : public std::true_type {};

template <class T>
struct IsConstMemberGetter : public std::false_type {};

template <class Ret, class Object>
struct IsConstMemberGetter<Ret (Object::*)() const> : public std::true_type {};

template <class T>
struct IsConstMemberSetter : public std::false_type {};

template <class ObjectType, class Arg>
struct IsConstMemberSetter<void (ObjectType::*)(Arg) const> : public
std::true_type {};

template <class ObjectType, class Ret, Ret (ObjectType::*Getter)()>
WrapperGetter<ObjectType, Ret, Getter> deduceWrapperForGetter();

template <class ObjectType, class Ret, Ret (ObjectType::*Getter)() const>
WrapperGetterConst<ObjectType, Ret, Getter> deduceWrapperForGetter();

template <class ObjectType, class Arg, void (ObjectType::*Setter)(Arg)>
WrapperSetter<ObjectType, Arg, Setter> deduceWrapperForSetter();

template <class ObjectType, class Arg, void (ObjectType::*Setter)(Arg) const>
WrapperSetterConst<ObjectType, Arg, Setter> deduceWrapperForSetter();

template <class ObjectType, class Arg>
Arg deduceSetterArg(void (ObjectType::*Setter)(Arg) const);

template <class ObjectType, class Arg>
Arg deduceSetterArg(void (ObjectType::*Setter)(Arg));

template <class ObjectType, class PropType>
auto deduceGetterRet(PropType (ObjectType::*Getter)() const, const
ObjectType * obj = 0) ->
typename EnableIf<IsConstMemberGetter<PropType (ObjectType::*)()
const>::value, decltype((obj->*Getter)())>::type;

template <class ObjectType, class PropType>
auto deduceGetterRet(PropType (ObjectType::*Getter)(), ObjectType * obj = 0) ->
typename EnableIf<!IsConstMemberGetter<PropType
(ObjectType::*)()>::value, decltype((obj->*Getter)()) >::type;

} //namespace detail

template <class PropType>
class TRWProperty {
    static_assert(!std::is_reference<PropType>::value,
                "Property types must not be reference types");
    PropType value_;
public:
    typedef typename std::remove_cv<PropType>::type value_type;
    typedef PropType & GetterReturnType;
    typedef const PropType & ConstGetterReturnType;

    /************************Constructors*************************************/

    ///Default constructor

    TRWProperty() = default;

    ///Construct from other property (rvalue)
    template <class OtherProp>
    TRWProperty(OtherProp && other,
    typename detail::EnableIf<detail::IsProperty<OtherProp>::value>::type
* = 0)
    : value_(std::move(other())) {}

    ///Construct from other value (rvalue)
    template <class PropVal>
    TRWProperty(PropVal && val,
    typename detail::EnableIf<!detail::IsProperty<PropVal>::value>::type * = 0)
    : value_(std::move(val)) {}

    ///Construct from other value (lvalue)
    template <class PropVal>
    TRWProperty(const PropVal & value,
    typename detail::EnableIf<!detail::IsProperty<PropVal>::value>::type * = 0)
    : value_(value) {}

    ///Construct from other property (lvalue)
    template <class OtherProp>
    TRWProperty(const OtherProp & prop,
    typename detail::EnableIf<detail::IsProperty<OtherProp>::value>::type
* = 0)
     : value_(prop()) {}

    //***************************Assignment
operators*****************************/

    ///Assign from other property (rvalue)
    template <class OtherProp>
    typename detail::EnableIf<detail::IsProperty<OtherProp>::value,
TRWProperty &>::type
    operator=(OtherProp && other) {
      value_ = std::move(other());
      return *this;
    }

    ///Assign from other value (rvalue)
    template <class PropValue>
    typename detail::EnableIf<!detail::IsProperty<PropValue>::value,
TRWProperty &>::type
    operator=(PropValue && val) {
      value_ = std::move(val);
      return *this;
    }

    ///Assign from other property (lvalue)
    template <class OtherProp>
    typename detail::EnableIf<detail::IsProperty<OtherProp>::value,
TRWProperty &>::type
    operator=(const OtherProp & other) {
      value_ = other();
      return *this;
    }

    ///Assign from other value (lvalue)
    template <class PropValue>
    typename detail::EnableIf<!detail::IsProperty<PropValue>::value,
TRWProperty &>::type
    operator=(const PropValue & val) {
      value_ = val;
      return *this;
    }

    /***************************Obtain value
operators*****************************/
    ConstGetterReturnType operator()() const {
        return value_;
    }

    GetterReturnType operator()() {
        return value_;
    }

    /****************************Implicit
conversions******************************/
    operator ConstGetterReturnType() const { return value_; }
    operator GetterReturnType() { return value_; }

    /******************************Arithmetic
Operators**********************************/
    template <class Prop>
    typename detail::EnableIf<detail::IsProperty<Prop>::value,
TRWProperty&>::type
    operator+=(const Prop & other)
    {
        (*this)() += other();
        return *this;
    }

    template <class PropValue>
    typename detail::EnableIf<!detail::IsProperty<PropValue>::value,
TRWProperty&>::type
    operator+=(const PropValue & value)
    {
        (*this)() += value;
        return *this;
    }

    TRWProperty &
    operator++()
    {
        ++((*this)());
        return *this;
    }

    TRWProperty & operator++(int) { ((*this)())++; return *this; }

    TRWProperty &
    operator--()
    {
        --((*this)());
        return *this;
    }

    TRWProperty & operator--(int) { ((*this)())--; return *this; }

    /*****************************Relational
operators**************************************/
    template <class Prop>
    typename detail::EnableIf<detail::IsProperty<Prop>::value, bool>::type
    operator<(const Prop & other) const
    {
        return (*this)() < other();
    }

    template <class PropValue>
    typename detail::EnableIf<!detail::IsProperty<PropValue>::value, bool>::type
    operator<(const PropValue & value) const
    {
        return (*this)() < value;
    }

    template <class Prop>
    typename detail::EnableIf<detail::IsProperty<Prop>::value, bool>::type
    operator==(const Prop & other) const
    {
        return (*this)() == other();
    }

    template <class PropValue>
    typename detail::EnableIf<!detail::IsProperty<PropValue>::value, bool>::type
    operator==(const PropValue & value) const
    {
        return (*this)() == value;
    }

    //******************************Swap***************************
    template <class OtherProp>
    void swap(OtherProp & other)
    {
        TRWProperty tmp(std::move(other));
        other = std::move(*this);
        *this = std::move(tmp);
    }
};

template <class PropType>
class TROProperty {
  //FIXME: Make private operator= and friend class the class
containing the property
    static_assert(!std::is_reference<PropType>::value,
                "Property types must not be reference types");
    PropType value_;
public:
    typedef typename std::remove_cv<PropType>::type value_type;
    typedef PropType & GetterReturnType;
    typedef const PropType & ConstGetterReturnType;

    /************************Constructors*************************************/

    ///Default constructor

    TROProperty() = default;

    ///Construct from other property (rvalue)
    template <class OtherProp>
    TROProperty(OtherProp && other,
    typename detail::EnableIf<detail::IsProperty<OtherProp>::value>::type
* = 0)
    : value_(std::move(other())) {}

    ///Construct from other value (rvalue)
    template <class PropVal>
    TROProperty(PropVal && val,
    typename detail::EnableIf<!detail::IsProperty<PropVal>::value>::type * = 0)
    : value_(std::move(val)) {}

    ///Construct from other value (lvalue)
    template <class PropVal>
    TROProperty(const PropVal & value,
    typename detail::EnableIf<!detail::IsProperty<PropVal>::value>::type * = 0)
    : value_(value) {}

    ///Construct from other property (lvalue)
    template <class OtherProp>
    TROProperty(const OtherProp & prop,
    typename detail::EnableIf<detail::IsProperty<OtherProp>::value>::type
* = 0)
     : value_(prop()) {}

    //***************************Assignment
operators*****************************/

    ///Assign from other property (rvalue)
    template <class OtherProp>
    typename detail::EnableIf<detail::IsProperty<OtherProp>::value,
TROProperty &>::type
    operator=(OtherProp && other) {
      value_ = std::move(other());
      return *this;
    }

    ///Assign from other value (rvalue)
    template <class PropValue>
    typename detail::EnableIf<!detail::IsProperty<PropValue>::value,
TROProperty &>::type
    operator=(PropValue && val) {
      value_ = std::move(val);
      return *this;
    }

    ///Assign from other property (lvalue)
    template <class OtherProp>
    typename detail::EnableIf<detail::IsProperty<OtherProp>::value,
TROProperty &>::type
    operator=(const OtherProp & other) {
      value_ = other();
      return *this;
    }

    ///Assign from other value (lvalue)
    template <class PropValue>
    typename detail::EnableIf<!detail::IsProperty<PropValue>::value,
TROProperty &>::type
    operator=(const PropValue & val) {
      value_ = val;
      return *this;
    }

    /***************************Obtain value
operators*****************************/
    ConstGetterReturnType operator()() const {
        return value_;
    }

    GetterReturnType operator()() {
        return value_;
    }

    /****************************Implicit
conversions******************************/
    operator ConstGetterReturnType() const { return value_; }
    operator GetterReturnType() { return value_; }

    /******************************Arithmetic
Operators**********************************/
    template <class Prop>
    typename detail::EnableIf<detail::IsProperty<Prop>::value,
TROProperty&>::type
    operator+=(const Prop & other)
    {
        (*this)() += other();
        return *this;
    }

    template <class PropValue>
    typename detail::EnableIf<!detail::IsProperty<PropValue>::value,
TROProperty&>::type
    operator+=(const PropValue & value)
    {
        (*this)() += value;
        return *this;
    }

    TROProperty &
    operator++()
    {
        ++((*this)());
        return *this;
    }

    TROProperty & operator++(int) { ((*this)())++; return *this; }

    TROProperty &
    operator--()
    {
        --((*this)());
        return *this;
    }

    TROProperty & operator--(int) { ((*this)())--; return *this; }

    /*****************************Relational
operators**************************************/
    template <class Prop>
    typename detail::EnableIf<detail::IsProperty<Prop>::value, bool>::type
    operator<(const Prop & other) const
    {
        return (*this)() < other();
    }

    template <class PropValue>
    typename detail::EnableIf<!detail::IsProperty<PropValue>::value, bool>::type
    operator<(const PropValue & value) const
    {
        return (*this)() < value;
      }

    template <class Prop>
    typename detail::EnableIf<detail::IsProperty<Prop>::value, bool>::type
    operator==(const Prop & other) const
    {
        return (*this)() == other();
    }

    template <class PropValue>
    typename detail::EnableIf<!detail::IsProperty<PropValue>::value, bool>::type
    operator==(const PropValue & value) const
    {
        return (*this)() == value;
    }

    //******************************Swap***************************
    template <class OtherProp>
    void swap(OtherProp & other)
    {
        TROProperty tmp(std::move(other));
        other = std::move(*this);
        *this = std::move(tmp);
    }
};

//***********************************************Elaborated
properties*******************************************
template <class GetterAddress, class SetterAddress>
class RWProperty {
    typedef typename GetterAddress::object_t ObjectType;

    ObjectType * object_;
    static SetterAddress setter_;
    static GetterAddress getter_;

    typedef decltype((object_->*GetterAddress::getter)()) GetterReturnType;
    typedef const decltype((object_->*GetterAddress::getter)())
ConstGetterReturnType;
    typedef typename std::remove_cv<GetterReturnType>::type value_type;
public:

    //Constructor without value
    RWProperty(ObjectType * object) :
    object_(object) {
    }

    //Constructor with value (lvalue)
    template <class PropValue>
    RWProperty(ObjectType * object, const PropValue & val,
    typename detail::EnableIf<!detail::IsProperty<PropValue>::value>::type
* = 0) :
    object_(object) {
        (object_->*setter_.setter)(val);
    }

    //Constructor with other property (lvalue)
    template <class OtherProp>
    RWProperty(ObjectType * object, const OtherProp & other,
    typename detail::EnableIf<detail::IsProperty<OtherProp>::value>::type
* = 0) :
    object_(object) {
        (object_->*setter_.setter)(other());
    }

    //Constructor with value (rvalue)
    template <class PropValue>
    RWProperty(ObjectType * object, PropValue && val,
    typename detail::EnableIf<!detail::IsProperty<PropValue>::value>::type
* = 0) :
    object_(object) {
        (object_->*setter_.setter)(std::move(val));
    }

    //Constructor with other property (rvalue)
    template <class OtherProp>
    RWProperty(ObjectType * object, OtherProp && other,
    typename detail::EnableIf<detail::IsProperty<OtherProp>::value>::type
* = 0) :
    object_(object) {
        (object_->*setter_.setter)(std::move(other()));
    }

    ConstGetterReturnType operator()() const {
        return (object_->*getter_.getter)();
    }

    GetterReturnType operator()() {
        return (object_->*getter_.getter)();
    }

    operator ConstGetterReturnType() const { (object_->*getter_.getter)(); }
    operator GetterReturnType() { return (object_->*getter_.getter)(); }

    ///Assign from other property (rvalue)

    template <class OtherProp>
    typename detail::EnableIf<detail::IsProperty<OtherProp>::value,
RWProperty &>::type
    operator=(OtherProp && other) {
      (object_->*setter_.setter)(std::move(other()));
      return *this;
    }

    ///Assign from other value (rvalue)
    template <class PropValue>
    typename detail::EnableIf<!detail::IsProperty<PropValue>::value,
RWProperty &>::type
    operator=(PropValue && val) {
      (object_->*setter_.setter)(std::move(val));
      return *this;
    }

    ///Assign from other property (lvalue)
    template <class OtherProp>
    typename detail::EnableIf<detail::IsProperty<OtherProp>::value,
RWProperty &>::type
    operator=(const OtherProp & other) {
      (object_->*setter_.setter)(other());
      return *this;
    }

    ///Assign from other value (lvalue)
    template <class PropValue>
    typename detail::EnableIf<!detail::IsProperty<PropValue>::value,
RWProperty &>::type
    operator=(const PropValue & val) {
      (object_->*setter_.setter)(val);
      return *this;
    }
         /******************************Arithmetic
Operators**********************************/
    template <class Prop>
    typename detail::EnableIf<detail::IsProperty<Prop>::value,
RWProperty&>::type
    operator+=(const Prop & other)
    {
        auto res = (*this)() + other();
        (object_->*setter_.setter)(res);
        return *this;
    }

    template <class PropValue>
    typename detail::EnableIf<!detail::IsProperty<PropValue>::value,
RWProperty&>::type
    operator+=(const PropValue & value)
    {
        auto res = (*this)() + value;
        (object_->*setter_.setter)(res);
        return *this;
    }

    RWProperty &
    operator++()
    {
        auto val = (*this)() + 1;
        (object_->*setter_.setter)(val);
        return *this;
    }

    RWProperty & operator++(int) { ++(*this); return *this; }

    RWProperty &
    operator--()
    {
        auto val = (*this)() - 1;
        (object_->*setter_.setter)(val);
        return *this;
    }

    RWProperty & operator--(int) { --(*this); return *this; }

    /*****************************Relational
operators**************************************/
    template <class Prop>
    typename detail::EnableIf<detail::IsProperty<Prop>::value, bool>::type
      operator<(const Prop & other) const
    {
        return (*this)() < other();
    }

    template <class PropValue>
    typename detail::EnableIf<!detail::IsProperty<PropValue>::value, bool>::type
    operator<(const PropValue & value) const
    {
        return (*this)() < value;
    }

    template <class Prop>
    typename detail::EnableIf<detail::IsProperty<Prop>::value, bool>::type
    operator==(const Prop & other) const
    {
        return (*this)() == other();
    }

    template <class PropValue>
    typename detail::EnableIf<!detail::IsProperty<PropValue>::value, bool>::type
    operator==(const PropValue & value) const
    {
        return (*this)() == value;
    }

    //******************************Swap***************************
    template <class OtherProp>
    void swap(OtherProp & other)
    {
            value_type tmp(std::move(other()));
            other = std::move(*this);
            *this = std::move(tmp);
    }

};

template <class GetterAddress, class SetterAddress>
GetterAddress RWProperty<GetterAddress, SetterAddress>::getter_;

template <class GetterAddress, class SetterAddress>
SetterAddress RWProperty<GetterAddress, SetterAddress>::setter_;

//***********************************************Elaborated
properties*******************************************
template <class GetterAddress, class SetterAddress>
class ROProperty {
    typedef typename GetterAddress::object_t ObjectType;

    ObjectType * object_;
    static SetterAddress setter_;
    static GetterAddress getter_;

    typedef decltype((object_->*GetterAddress::getter)()) GetterReturnType;
    typedef const decltype((object_->*GetterAddress::getter)())
ConstGetterReturnType;
    typedef typename std::remove_cv<GetterReturnType>::type value_type;
public:

    //Constructor without value
    ROProperty(ObjectType * object) :
    object_(object) {
    }

    //Constructor with value (lvalue)
    template <class PropValue>
    ROProperty(ObjectType * object, const PropValue & val,
    typename detail::EnableIf<!detail::IsProperty<PropValue>::value>::type
* = 0) :
    object_(object) {
        (object_->*setter_.setter)(val);
    }

    //Constructor with other property (lvalue)
    template <class OtherProp>
    ROProperty(ObjectType * object, const OtherProp & other,
    typename detail::EnableIf<detail::IsProperty<OtherProp>::value>::type
* = 0) :
    object_(object) {
        (object_->*setter_.setter)(other());
    }

    //Constructor with value (rvalue)
    template <class PropValue>
    ROProperty(ObjectType * object, PropValue && val,
    typename detail::EnableIf<!detail::IsProperty<PropValue>::value>::type
* = 0) :
    object_(object) {
        (object_->*setter_.setter)(std::move(val));
    }

    //Constructor with other property (rvalue)
    template <class OtherProp>
    ROProperty(ObjectType * object, OtherProp && other,
    typename detail::EnableIf<detail::IsProperty<OtherProp>::value>::type
* = 0) :
    object_(object) {
        (object_->*setter_.setter)(std::move(other()));
    }

    ConstGetterReturnType operator()() const {
        return (object_->*getter_.getter)();
    }

    GetterReturnType operator()() {
        return (object_->*getter_.getter)();
    }

    operator ConstGetterReturnType() const { (object_->*getter_.getter)(); }
    operator GetterReturnType() { return (object_->*getter_.getter)(); }

    ///Assign from other property (rvalue)

    template <class OtherProp>
    typename detail::EnableIf<detail::IsProperty<OtherProp>::value,
ROProperty &>::type
    operator=(OtherProp && other) {
      (object_->*setter_.setter)(std::move(other()));
      return *this;
    }

    ///Assign from other value (rvalue)
    template <class PropValue>
    typename detail::EnableIf<!detail::IsProperty<PropValue>::value,
ROProperty &>::type
    operator=(PropValue && val) {
      (object_->*setter_.setter)(std::move(val));
      return *this;
    }

    ///Assign from other property (lvalue)
    template <class OtherProp>
    typename detail::EnableIf<detail::IsProperty<OtherProp>::value,
ROProperty &>::type
    operator=(const OtherProp & other) {
      (object_->*setter_.setter)(other());
      return *this;
    }

    ///Assign from other value (lvalue)
    template <class PropValue>
    typename detail::EnableIf<!detail::IsProperty<PropValue>::value,
ROProperty &>::type
    operator=(const PropValue & val) {
      (object_->*setter_.setter)(val);
      return *this;
    }
         /******************************Arithmetic
Operators**********************************/
    template <class Prop>
    typename detail::EnableIf<detail::IsProperty<Prop>::value,
ROProperty&>::type
    operator+=(const Prop & other)
    {
        auto res = (*this)() + other();
        (object_->*setter_.setter)(res);
        return *this;
    }

    template <class PropValue>
    typename detail::EnableIf<!detail::IsProperty<PropValue>::value,
ROProperty&>::type
    operator+=(const PropValue & value)
    {
        auto res = (*this)() + value;
        (object_->*setter_.setter)(res);
        return *this;
    }

    ROProperty &
    operator++()
    {
        auto val = (*this)() + 1;
        (object_->*setter_.setter)(val);
        return *this;
    }

    ROProperty & operator++(int) { ++(*this); return *this; }

    ROProperty &
    operator--()
    {
        auto val = (*this)() - 1;
        (object_->*setter_.setter)(val);
        return *this;
    }

    ROProperty & operator--(int) { --(*this); return *this; }

    /*****************************Relational
operators**************************************/
    template <class Prop>
    typename detail::EnableIf<detail::IsProperty<Prop>::value, bool>::type
    operator<(const Prop & other) const
    {
        return (*this)() < other();
    }

    template <class PropValue>
    typename detail::EnableIf<!detail::IsProperty<PropValue>::value, bool>::type
    operator<(const PropValue & value) const
    {
        return (*this)() < value;
    }

    template <class Prop>
    typename detail::EnableIf<detail::IsProperty<Prop>::value, bool>::type
    operator==(const Prop & other) const
    {
        return (*this)() == other();
    }

    template <class PropValue>
    typename detail::EnableIf<!detail::IsProperty<PropValue>::value, bool>::type
    operator==(const PropValue & value) const
    {
        return (*this)() == value;
    }

    //******************************Swap***************************
    template <class OtherProp>
    void swap(OtherProp & other)
    {
            value_type tmp(std::move(other()));
            other = std::move(*this);
            *this = std::move(tmp);
    }

};

template <class GetterAddress, class SetterAddress>
GetterAddress ROProperty<GetterAddress, SetterAddress>::getter_;

template <class GetterAddress, class SetterAddress>
SetterAddress ROProperty<GetterAddress, SetterAddress>::setter_;

} //namespace props

#define PROPS_RWPROPERTY(propname) \
        ::props::RWProperty< \
        decltype(::props::detail::deduceWrapperForGetter<ClassName, \
        decltype(::props::detail::deduceGetterRet(&ClassName::get##propname)), \
        &ClassName::get##propname>()), \
        decltype(::props::detail::deduceWrapperForSetter<ClassName, \
        decltype(::props::detail::deduceSetterArg(&ClassName::set##propname)), \
        &ClassName::set##propname>())> propname

#define PROPS_ROPROPERTY(propname) \
        ::props::ROProperty< \
        decltype(::props::detail::deduceWrapperForGetter<ClassName, \
        decltype(::props::detail::deduceGetterRet(&ClassName::get##propname)), \
        &ClassName::get##propname>()), \
        decltype(::props::detail::deduceWrapperForSetter<ClassName, \
        decltype(::props::detail::deduceSetterArg(&ClassName::set##propname)), \
        &ClassName::set##propname>())> propname

#endif


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk