Свойство (Property)

Пример

# include <iostream>
# include <memory>

using namespace std;

template <typename Owner, typename Type>
class Property
{
        using Getter = Type(Owner::*)() const;
        using Setter = void (Owner::*)(const Type&);
private:
        Owner* owner;
        Getter methodGet;
        Setter methodSet;

public:
        Property() = default;
        Property(Owner* const owr, Getter getmethod, Setter setmethod) : owner(owr), methodGet(getmethod), methodSet(setmethod) 
{}

        void init(Owner* const owr, Getter getmethod, Setter setmethod)
        {
                owner = owr;
                methodGet = getmethod;
                methodSet = setmethod;
        }

        operator Type() { return (owner->*methodGet)(); }        // Getter
        void operator=(const Type& data) { (owner->*methodSet)(data); }        // Setter

//        Property(const Property&) = delete;
//        Property& operator=(const Property&) = delete;
};

class Object
{
private:
        double value;

public:
        Object(double v) : value(v) { Value.init(this, &Object::getValue, &Object::setValue); }

        double getValue() const { return value; }
        void setValue(const double& v) { value = v; }

        Property<Object, double> Value;
};

int main()
{
        Object obj(5.);
        
        cout << "value = " << obj.Value << endl;
        
        obj.Value = 10.;
        
        cout << "value = " << obj.Value << endl;
        
        unique_ptr<Object> ptr = make_unique<Object>(15.);
        
        cout << "value =" << ptr->Value << endl;
        
        obj = *ptr;
        obj.Value = ptr->Value;
}

Пример. Специализация для ReadOnly и WriteOnly

# include <iostream>

using namespace std;

struct ReadOnly_tag {};
struct WriteOnly_tag {};
struct ReadWrite_tag {};

template <typename Owner, typename Type, typename Access = ReadWrite_tag>
class Property
{
        using Getter = Type(Owner::*)() const;
        using Setter = void (Owner::*)(const Type&);
        private:
        Owner* owner;
        Getter methodGet;
        Setter methodSet;

public:
        Property() = default;
        Property(Owner* const owr, Getter getmethod, Setter setmethod) : owner(owr), methodGet(getmethod), methodSet(setmethod) 
{}

        void init(Owner* const owr, Getter getmethod, Setter setmethod)
        {
                owner = owr;
                methodGet = getmethod;
                methodSet = setmethod;
        }

        operator Type() { return (owner->*methodGet)(); }// Getter
        void operator=(const Type& data) { (owner->*methodSet)(data); }// Setter
};

template<typename Owner, typename Type>
class Property<typename Owner, typename Type, ReadOnly_tag>
{
        using Getter = Type(Owner::*)() const;
private:
        Owner* owner;
        Getter methodGet;

public:
        Property() = default;
        Property(Owner* const owr, Getter getmethod) : owner(owr), methodGet(getmethod) {}
        
        void init(Owner* const owr, Getter getmethod)
        {
                owner = owr;
                methodGet = getmethod;
        }

operator Type() { return (owner->*methodGet)(); }// Getter
};

template<typename Owner, typename Type>
class Property<typename Owner, typename Type, WriteOnly_tag>
{
        using Setter = void (Owner::*)(const Type&);
private:
        Owner* owner;
        Setter methodSet;

public:
        Property() = default;
        Property(Owner* const owr, Setter setmethod) : owner(owr), methodSet(setmethod) {}
        
        void init(Owner* const owr, Setter setmethod)
        {
                owner = owr;
                methodSet = setmethod;
        }

        void operator=(const Type& data) { (owner->*methodSet)(data); }// Setter
};

class Object
{
public:
        Object(double vRW = 0., double vRO = 0., double vWO = 0.)
                : valueRW(vRW), valueRO(vRO), valueWO(vWO)
        {
                ValueRW.init(this, &Object::getValueRW, &Object::setValueRW);
                ValueRO.init(this, &Object::getValueRO);
                ValueWO.init(this, &Object::setValueWO);
        }

private:
        double valueRW;

public:
        Property<Object, double> ValueRW;
        
        double getValueRW() const { return valueRW; }
        void setValueRW(const double& v) { valueRW = v; }

private:
        double valueRO;

public:
        Property<Object, double, ReadOnly_tag> ValueRO;

        double getValueRO() const { return valueRO; }

private:
        double valueWO;

public:
        Property<Object, double, WriteOnly_tag> ValueWO;

        void setValueWO(const double& v) { valueWO = v; }
};

void main()
{
        Object obj(5., 15., 25.);
        
        obj.ValueRW = 10.;
        cout << "value = " << obj.ValueRW << endl;
        
        //        obj.ValueRO = 10.;        //         Error! (ReadOnly) 
        cout << "value = " << obj.ValueRO << endl;
        
        obj.ValueWO = 10.;
        //        cout << "value = " << obj.ValueWO << endl;// Error! (WriteOnly)
}

Last updated