Reputation: 14603
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?
Upvotes: 3
Views: 823
Reputation: 4813
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.
Upvotes: 1
Reputation: 4275
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
It shoud be easy to implement the getter function in a similar way.
Upvotes: 0