my new property class

i'm doing my new property class, but i'm stuck with functions :(
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <iostream>
#include <functional>

using namespace std;

template <typename T>
class property
{
private:
    T PropertyValue;
    std::function<void(void)> getf=NULL;
    std::function<void(T a)> setf=NULL;
public:
    property()
    {
        //nothing
    };

    property(std::function<void(void)> GetFunction,std::function<T(void)> SetFunction)
    {
        setf=SetFunction;
        getf=GetFunction;
    }

    property& operator=(T value)
    {
        if(setf==NULL)
            PropertyValue=value;
        else
            setf(value);
        return *this;
    }

    T& operator=(property value)
    {
        if(getf==NULL)
            return PropertyValue;
        else
            return getf();
    }

    friend ostream& operator<<(ostream& os, const property& dt)
    {
        os << dt.PropertyValue;
        return os;
    }

    friend istream& operator>>(istream &input,property &dt)
    {
        input>>dt.PropertyValue;
        return input;
    }
};

class test
{
public:
    property<string> Name;
    property<int> Age;
};

test a;
int main()
{
    a.Name="joaquim "  "Miguel";
    a.Age=10+15;
    cout << a.Name << endl;
    cout << "what is your name?\n";
    cin >> a.Name;
    cout << "your name is: " << a.Name << endl;
    return 0;
}

the code works like a charm. but imagine that i need more with Get and Set functions, how can i connect them to the T PropertyValue on class property?
yes... i'm a little confuse.... :(
now i did these new test:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <iostream>
#include <functional>

using namespace std;

template <typename T>
class property
{
private:
    T PropertyValue;
    std::function<void(void)> getf=NULL;
    std::function<void(T a)> setf=NULL;
public:
    property()
    {
        //nothing
    };

    property(std::function<void(void)> GetFunction,std::function<T(void)> SetFunction)
    {
        setf=SetFunction;
        getf=GetFunction;
    }

    property& operator=(T value)
    {
        if(setf==NULL)
            PropertyValue=value;
        else
            setf(value);
        return *this;
    }

    T& operator=(property value)
    {
        if(getf==NULL)
            return PropertyValue;
        else
            return getf();
    }

    friend ostream& operator<<(ostream& os, const property& dt)
    {
        os << dt.PropertyValue;
        return os;
    }

    friend istream& operator>>(istream &input,property &dt)
    {
        input>>dt.PropertyValue;
        return input;
    }
};

void sethi(string b)
{
    b = b + " hi";
}

string gethi()
{
    return "hello";
}

class test
{
public:
    property<string> Name(&sethi,&gethi);
    property<int> Age;
};

test a;
int main()
{
    a.Name="joaquim "  "Miguel";
    a.Age=10+15;
    cout << a.Name << endl;
    cout << "what is your name?\n";
    cin >> a.Name;
    cout << "your name is: " << a.Name << endl;
    return 0;
}

but i get several errors and warnings.
please can anyone advice me?
now the property works. but i have 1 problem with:
when i use it inside the class(test, for exemple), the 1st test instance works, but not the other instances :(
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
template <typename T>
class property
{
private:
    T PropertyValue;
    std::function<T(void)> getf;
    std::function<void(T)> setf;
public:

    property(T value)
    {
        PropertyValue=value;
    };

    property(std::function<T(void)> GetFunction=nullptr,std::function<void(T)> SetFunction=nullptr)
    {
        setf=SetFunction;
        getf=GetFunction;
    }

    property& operator=(T value)
    {
        if(getf==nullptr || setf==nullptr)
            PropertyValue=value;
        else
            setf(value);
        return *this;
    }

    T& operator=(property value)
    {
        if(value.getf==nullptr || value.setf==nullptr)
            return value.PropertyValue;
        else
            return value.getf();
    }


    friend ostream& operator<<(ostream& os, const property& dt)
    {
        if(dt.getf==nullptr && dt.setf==nullptr)
            os << dt.PropertyValue;
        else if (dt.getf!=nullptr)
            os << dt.getf();
        return os;
    }

    friend istream& operator>>(istream &input, property &dt)
    {
        input >> dt.PropertyValue;
        if (dt.setf!=nullptr)
            dt.setf(dt.PropertyValue);
        return input;
    }

    friend istream &getline(istream &in, property &dt)
    {
        getline(in, dt.PropertyValue);
        if (dt.setf!=nullptr)
            dt.setf(dt.PropertyValue);
        return in;
    }
};

i belive these is a pointer instance problem... or my class property have 1 error, that i don't know :(
please can anyone advice me?
what are you trying to achieve with that class?
just create properties in a class for use the '=' operator instead the get and set functions.
but, like you see, i create the property with just 1 line of code ;)
right now you get the same result with:
1
2
3
4
5
6
class test
{
public:
    string Name;
    int Age;
};


The functions sethi and gethi are completely unrelated to anything within the class property. So I don't see the use of it.

I really don't see the use of property?
ok... teste these entire code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include <iostream>
#include <sstream>

using namespace std;

template <typename T>
class property
{
private:
    T PropertyValue;
    std::function<T(void)> getf;
    std::function<void(T)> setf;
public:

    property(T value)
    {
        PropertyValue=value;
    };

    property(std::function<T(void)> GetFunction=nullptr,std::function<void(T)> SetFunction=nullptr)
    {
        setf=SetFunction;
        getf=GetFunction;
    }

    property& operator=(T value)
    {
        if(getf==nullptr || setf==nullptr)
            PropertyValue=value;
        else
            setf(value);
        return *this;
    }

    T& operator=(property value)
    {
        if(value.getf==nullptr || value.setf==nullptr)
            return value.PropertyValue;
        else
            return value.getf();
    }


    friend ostream& operator<<(ostream& os, const property& dt)
    {
        if(dt.getf==nullptr && dt.setf==nullptr)
            os << dt.PropertyValue;
        else if (dt.getf!=nullptr)
            os << dt.getf();
        return os;
    }

    friend istream& operator>>(istream &input, property &dt)
    {
        input >> dt.PropertyValue;
        if (dt.setf!=nullptr)
            dt.setf(dt.PropertyValue);
        return input;
    }

    friend istream &getline(istream &in, property &dt)
    {
        getline(in, dt.PropertyValue);
        if (dt.setf!=nullptr)
            dt.setf(dt.PropertyValue);
        return in;
    }
};

template<typename T, typename Fnc1_t, typename Fnc2_t, typename classthis>
property<T> GetProperty(Fnc1_t Getter, Fnc2_t Setter, classthis clsthis)
{
    return property<T>(std::bind(Getter, clsthis), std::bind(Setter, clsthis, std::placeholders::_1));
}

#define PROPERTY(TypeName,PropertyName,getfunction, setfunction) \
property<TypeName> PropertyName{std::bind(&getfunction, this),std::bind(&setfunction, this, std::placeholders::_1)}

class test
{
public:
    int x;
    int y;
    int getx()
    {
        return x;
    }
    void setx(int value)
    {
        x=value;
    }
    int gety()
    {
        return y;
    }
    void sety(int value)
    {
        y=value;
    }
public:
    std::string go()
    {
        std::ostringstream out;
        out << '(' << x << ',' << y << ')' << ':' << x + y << '\n';
        return(out.str());
    }


    test()
    {

    }
    property<int> X=GetProperty<int>(&test::getx, &test::setx,this);
    //PROPERTY(int, X,test::getx, test::setx);
    PROPERTY(int, Y,test::gety, test::sety);
};

int main()
{
    test a;
    cout << "what is the x?\n";
    cin >> a.X;
    cout << "what is the y?\n";
    cin >> a.Y;
    cout << "\nhere is the result:\n" << a.go() << '\n';
    test b = a;
    cout << b.x << "\t" << b.y << endl;
    cout << "what is a different x?\n";
    cin >> b.X;
    cout << "what is a different y?\n";
    cin >> b.Y;
    cout << "\nhere is the result:\n" << b.go() << '\n';
    cout << "\noh wait, no; here is the result:\n" << a.go() << '\n';
    return 0;
}

just compile and execute and you will see what i mean of the error.
yes i can have normal variables, but these is a normal test for my property class
Yes, I see what's wrong. It's an really sophisticated way to shoot yourself in the foot;)

the problem is rather easy. On line 126 you copy everything including the function objects which include the this pointer of a. Which means even though you access b you really modify a
realy i never knew that... thanks for correct me... thanks
before you shoot me, take off the bullets, please ;)
that problem can be resolved with my class or it's a C++ thing?
I haven't looked at the code, except to note that property<T> is a Copyable and Moveable type.

That being the case, clients can trivially violate the encapsulation of the property.
Any one can bypass the setter and assign directly to the property. For instance:

1
2
3
4
5
6
7
8
int main()
{
    some_class_with_properties a;
    
    decltype(a.some_int_property) my_value(1234);

    std::swap( a.some_int_property, my_value ) ;
}


but how can i avoid that problem?
The property needs to have a narrow interface which is accessible to everyone; the narrow interface provides just the get and set functionality.

And a wide interface which is only accessible to the class that contains the property. Constructors and other foundation operations would be part of this wide interface.

Something along these lines (caveat: this is merely an illustrative outline sketch):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include <functional>
#include <iostream>

template < typename T, typename C > struct property // getter elided for brevity
{
    ////////////// the narrow interface is public //////////////////

    operator const T& () const& { return value ; }
    operator T () const&& { return value ; }

    property<T,C>& operator= ( const T& v )
    { if(setter) setter(v) ; else value = v ; return *this ; }

    // compound assignment operators (if required)
    // eg.
    property<T,C>& operator+= ( const T& v )
    {
        if(setter) setter(value+v) ; else value += v ;
        return *this ;
    }

    private:
        T value ;

        using setter_type = std::function< void( const T& ) > ;
        std::function< void( const T& ) > setter ;

        ////////////// the wide interface is private //////////////////

        property( T&& v ) : value( std::move(v) ) {}

        property( const T& v = T() ) : value(v) {}

        template < typename FN, typename... ARGS >
        property( const T& v, FN fn, ARGS... args ) : value(v),
                 setter( std::bind( fn, args..., std::placeholders::_1 ) ) {}

        // additional constructors (if required)

        property<T,C>( const property<T,C>& ) = default ;
        property<T,C>( property<T,C>&& ) = default ;
        property<T,C>& operator= ( const property<T,C>& ) = default ;
        property<T,C>& operator= ( property<T,C>&& ) = default ;

        ////////////// the containing class is a friend  //////////////////
        ////////////// and can access the wide interdace //////////////////
        friend C ;
};

template < typename CHAR_TYPE, typename TRAITS_TYPE, typename T, typename C >
std::basic_ostream<CHAR_TYPE,TRAITS_TYPE>&
operator << ( std::basic_ostream<CHAR_TYPE,TRAITS_TYPE>& stm, 
              const property<T,C>& prop ) { return stm << T(prop) ; }

#include <string>

struct A
{
    property<std::string,A> name{ "anonymous", &A::set_name, this, 3 };

    property<double,A> amount{ 12.3, &A::set_amount, this } ;

    private:
        void set_amount( double d )
        { /* validate */ amount.value = d ; std::cout << "set_amount\n" ; }

        void set_name( int excl, std::string new_name )
        {
            /* validate */
            name.value = new_name + std::string( excl, '!') ;
            std::cout << "set_name\n" ;
        }
};

int main()
{
    A a ;
    std::cout << a.name << ' ' << a.amount << '\n' ;

    a.name = "Cambalinho" ;
    a.amount += 567.89 ;

    std::cout << a.name << ' ' << a.amount << '\n' ;

    #ifdef TRY_BYPASS_SETTER
        decltype(a.amount) my_value(1234) ; // ***error: constructor is private
        std::swap( a.amount, my_value ) ; // ***error: move constructor is private
    #endif // TRY_BYPASS_SETTER
}

http://coliru.stacked-crooked.com/a/75d6657718276214
Topic archived. No new replies allowed.