3

I find, when coding C++ code, that I spend a lot of time writing accessor boiler plate code, such as:

class A
{
  int x;

public:
  auto x();
  void set_x(decltype(x));
};

The whole idea of implementing accessors revolves around being able to intercept read and write accesses to them. I stumbled on this library (I'm not the author). It really makes me wonder, if, to avoid having to write boilerplate code, one could/should just write something like:

class A
{
public:
  property<int> x;

  A() {
    x.setter([this](int){ /* setter code */ });
  }
};

My question is: What techniques are available to avoid having to write a lot of boilerplate code for getters and setters?

TobiMcNamobi
  • 4,687
  • 3
  • 33
  • 52
user1095108
  • 14,119
  • 9
  • 58
  • 116
  • 1
    This is opinion-based but if you look at the implementation of `property` in the link you provided, you'll see that it add a lot of overhead... This may be ok if you are building an UI, but not if you are doing some core programming. Plus, in my (subjective) opinion, it is harder to read code where you have overloaded `operator=` everywhere. – Holt May 24 '16 at 10:34
  • I wasn't referring to the library in particular, it's just an example, the implementation of `property<>` is arbitrary. – user1095108 May 24 '16 at 10:36
  • Also, you neglect that you can have `light_property<>`, `heavy_property<>` implementations. – user1095108 May 24 '16 at 10:49
  • 2
    Why do you need all these getters and setters in the first place? Serialization? – mkluwe May 24 '16 at 11:37
  • @mkluwe http://stackoverflow.com/questions/1568091/why-use-getters-and-setters – user1095108 May 24 '16 at 12:02
  • 1
    @user1095108 There are good arguments for "using accessors rather than directly exposing fields of a class", but generally neither is necessary, and many consider this an anti pattern. If there's some real program logic (e.g. a setter with some validation) I won't rate that as boilerplate. – mkluwe May 24 '16 at 14:57
  • 1
    @mkluwe Agreed. Furthermore it's a bad idea to name a function with real program logic just getX() or setX() because of [POLA](https://en.wikipedia.org/wiki/Principle_of_least_astonishment). – TobiMcNamobi May 25 '16 at 08:24

2 Answers2

1

There is some discussion here and there about whether getters and setters are evil in general.

So, my strategy for avoiding boilerplate code: Try to avoid getters and setters. When in need of some pure data class I declare the (few) fields public. But in these cases I try to avoid giving them any other logic, I try to keep these classes as little as possible.

Also, read about tell-don't-ask, e.g. from Martin Fowler.

TobiMcNamobi
  • 4,687
  • 3
  • 33
  • 52
0

I guess you are looking for something like this:

template <typename T>
class Property{
    private:

    T val;

    std::function<void(T& v,const T& newV)> setFN = nullptr;

    public:

    void setter(decltype(setFN) newSetter){
        setFN = newSetter;
    }

    void set(const T& newVal){
        if(!setFN)
            val = newVal;
        else
            setFN(val,newVal);
    }

    T get(){
        return val;
    }
};

So basically a template class, that is able to store a setter-function. If one is stored, it is called, if not, just a operator= is used (which needs to be defined by T, of course).

Usage:

int main() {

    Property<int> x;

    x.set(5);
    std::cout << x.get() << std::endl;

    x.setter([](int& v, const int& newV){std::cout << "Setter called\n"; v=newV;});

    x.set(2);
    std::cout << x.get() << std::endl;

    return 0;
}

Output:

5
Setter called
2

Try it online

It shoud be easy to implement the getter function in a similar way.

Anedar
  • 4,235
  • 1
  • 23
  • 41
  • The question was a bit broader :), I wasn't really asking for an implementation. – user1095108 May 24 '16 at 10:41
  • Ok, then i missunderstood you - im not aware of special "techniques" rather than writing a simple template class like this and reusing it... – Anedar May 24 '16 at 10:43