boriel.com

Hacks, science and curiosities

Properties in C++

– 🕓 2 min read

In a previous post I wrote about Python's elegance and some tips to make your code look even fancier and closer to the English language. I'm currently rather busy programming in C++, a language I have not used for 2 years, and the code certainly looks dirtier. :(

Sometimes I want to make a class attribute private, so in order to access it one has to implement a read method and (if needed) a write one. They're called getter and setter respectively (I'm not very fond of private attributes, by the way). This usually happens when the external representation of the attribute value differs with the internal one. Both Microsoft Visual C++ and Borland Builder C++ implement getters and setters in their own way, but I prefer a standard method which can be used across every C++ standard compiler (including Intel C++ and G++, the GNU C++ compiler). Finally I worked out a solution and implemented this template, and it seems to work. Basically, it implements properties as classes:

template <typename T, class F> class Property
{
private:
    T data;
    F *_instance;
    T (F::*_getter)(void);
    T (F::*_setter)(const T &);

public:
    Property(F *instance,
                T (F::*getter)(void),
                T (F::*setter)(const T &) = NULL)
    {
        _instance = instance;
        _getter = getter;
        _setter = setter;
    }

    Property(F *instance,
                    T initialValue, 
                    T (F::*getter)(void),
                    T (F::*setter)(const T &) = NULL)
    {
        _instance = instance;
        _getter = getter;
        _setter = setter;
        data = initialValue;
    }

    Property()
    {
    }

    inline operator T()
                { return (_instance->*_getter)(); }

    inline T operator =(const T &value)
                { return (_instance->*_setter)(value); }

    friend F;
};

You will usually put this template into an include file.

Now an example. It creates an <int> container (stored in an STL <vector>), with a length property. Reading this property returns vector.size() value, whilst setting a value to length will effectively resize the vector:

class IntVector {

private:
        int __setSize(const int &newValue) {
            vectorData.resize(newValue);
            return vectorData.size();
        }

        int __getSize(void) {
            return vectorData.size();
        }

public:
        std::vector<int> vectorData;

        Property<int, IntVector> length;

        IntVector():
            length(this, &IntVector::__getSize, &IntVector::__setSize)
        {
        }
};

int main(int argc, char *argv[])
{
        IntVector myVector;

        myVector.length = 32; // Sets the vector size to 32 elements
        cout << "Vector size: " << myVector.length; 

        return EXIT_SUCCESS;
}

Remember:

        myVector.length = 32; // Sets the vector size to 32 elements

effectively sets the vector length and

        variable = myVector.length; // Reads the vector size

read such length.

Note: This code is released with a CC0 (Public Domain) license, so you can use it for whatever you want.

Read more: