Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Property-like variable in C++

Tags:

c++

properties

I know that the implementation of property-like objects has been discussed many times, but what I need is slightly different from the various solutions proposed.

What I want is an object that has the same semantics of a variable, but when its value is changed I want to perform some action. This means having implicit get/set methods, implemented overloading the operator = and the implicit conversion operator.

Please note that when I mean "property-like" I don't mean necessarily the semantic object.property, but just a way to have implicit get/set methods (as in property-like-variable = value). The reason is that I have some existing code that uses a variable, I want to perform some action every time the variable value changes without changing the existing code (only the declaration of the variable should change).

I have obtained this result with a minimal code like this:

#include <stdio.h>

class Int
{
    int _value;

public:
    // default constructor
    Int() { printf("Int: initial value undefined\n"); }

    // assignment constructor
    Int(int value) : _value(value) { printf("Int: initial value is %d\n", _value); }

    // property get
    operator const int() const { return _value; }

    // property set
    int operator=(int value)
    { 
        _value = value;
        printf("new value is %d\n", value);
        return value;
    }

    // TODO: overload other operators if needed
};

This is a sample usage:

class C
{
    Int _i;

public:
    C() : _i(2) { }

    void foo()
    {
        _i = 3;
        printf("foo(): _i = %d\n", _i);
    }
};

int main()
{
    int i;
    Int I;

    i = 1;
    I = i;
    I = I + 1;

    C c;
    c.foo();
}

Now some questions:

  1. Has this specific need already been discussed? There's a design pattern?
  2. I'm doing something bad here? (both from an implementation and design point of view)
  3. There's some performance-wise disadvantage in doing this or the compiler is able to optimize it without having an overhead?
  4. There's a better way to call this construct? Because this seems not strictly a "property" (this seems more similar to "boxing" a variable in a class).
  5. Can this be generalized with templates? I don't see a simple way to do it, because the need to do this stuff is to perform custom stuff when getting/setting the value.
like image 271
lornova Avatar asked Oct 22 '22 15:10

lornova


1 Answers

Ad question 2: I see two general issues with your code:

  1. the first const qualifier in your operator const int() declaration is meaningless (gcc warns about it)

  2. the return type of the assignment operator should be Int& not int otherwise it will have different semantics than the one of the original int and the following c++ code will not compile:

    Int i;
    (i=2)=3;
    

Ad question 3: if your set/get functions do nothing but assign/return the value they should be optimized out completely. If you call printf() though, you might seriously get into performance trouble ;).

Ad question 5: The generalization with templates seems strait forward, including customizing it for different types via template sepcialization:

template<typename T> class observe
{
    T _value;

public:
    // default constructor
    observe() { cout << "Int: initial value undefined" << endl; }

    // assignment constructor
    observe(const T& v) : _value(v) { cout << "initial value is " << v << endl; }

    // property get
    operator T() const { return _value; }

    // property set
    observe<T>& operator=(const T& value)
    {
        _value = value;
        cout << "new value is " << _value << endl;
        return *this;
    }
};

// special behavior for the assignment of doubles
template<> observe<double>& observe<double>::operator =(const double& value)
{
    _value = value;
    cout << "new double value is " << _value << endl;
    return *this;
}

observe<double> d;
d = 1.0;
like image 50
axxel Avatar answered Oct 29 '22 15:10

axxel