# Свойство (Property)

## Пример

```cpp
# 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

<pre class="language-cpp"><code class="lang-cpp"># include &#x3C;iostream>

using namespace std;

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

template &#x3C;typename Owner, typename Type, typename Access = ReadWrite_tag>
class Property
{
        using Getter = Type(Owner::*)() const;
        using Setter = void (Owner::*)(const Type&#x26;);
        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&#x26; data) { (owner->*methodSet)(data); }// Setter
};

template&#x3C;typename Owner, typename Type>
class Property&#x3C;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&#x3C;typename Owner, typename Type>
class Property&#x3C;typename Owner, typename Type, WriteOnly_tag>
{
        using Setter = void (Owner::*)(const Type&#x26;);
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&#x26; 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, &#x26;Object::getValueRW, &#x26;Object::setValueRW);
                ValueRO.init(this, &#x26;Object::getValueRO);
                ValueWO.init(this, &#x26;Object::setValueWO);
        }

private:
        double valueRW;

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

private:
        double valueRO;

public:
        Property&#x3C;Object, double, ReadOnly_tag> ValueRO;

        double getValueRO() const { return valueRO; }

private:
        double valueWO;

public:
        Property&#x3C;Object, double, WriteOnly_tag> ValueWO;

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

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

</code></pre>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://frogs-organization-2.gitbook.io/oop.-sbornik./23.-patterny-povedeniya./svoistvo-property.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
