I was in experimenting mood again. I got annoyed by writing the following code over and over again:
class Test {
private:
int myVar;
public:
int GetMyVar() { return myVar; }
}
Sometimes additionally to that a Setter method which processes or checks the values.
So how to make this more compact? With macro hacking! jippie! Yep macros are bad, but sometimes its nice to make some experiments, so here we go.
Simple read only properties
Well the most used case for me is: I want a property that can be read from the outside, but can only be written from “inside” the class.
So here we go:
class Test : EnableProperties<test> {
public:
Property(ReadOnly, std::string) MyVar;
}
Uuuh, magic macro hacking. So what can we do now with this variable? With the operator() we can set and get the value of this property, but for ease of use we can also use implicit conversion.
Test test;
test.MyVar("New String"); // Access Error
std::string a = test.MyVar(); // Yep
std::string b = test.MyVar; // Fine too
Custom getter and setter
Lets just say we want to do process the value of the property on each get. With even more macro and template hacking we get this:
class Test : EnableProperties<test> {
public:
CustomProperty(Public, int) {
Getter {
return value * 42;
}
} MyVar;
}
Test test;
test.MyVar(10);
std::cout << test.MyVar() << std::endl; // 420
I think this is a pretty funny experiment. There are still some issues left. For example: the custom getter and setter feature only works with VC. Still it is an very interesting concept and I think I will investigate it a little bit further.
Code
Want to see the strange macro hacking? Sure here you go :)
template<typename friendclass typename t,> class ReadonlyProperty {
protected:
typedef T ValueType;
friend FriendClass;
ValueType value;
virtual void Set(const ValueType& newValue) { value = newValue; }
virtual const ValueType& Get() { return value; }
public:
inline void operator()(const ValueType& newValue) { Set(newValue); }
inline const ValueType& operator()() { return Get(); }
inline operator ValueType() { return Get(); }
};
template<typename friendclass typename t,> class PublicProperty {
protected:
typedef T ValueType;
friend FriendClass;
ValueType value;
public:
virtual void Set(const ValueType& newValue) { value = newValue; }
virtual const ValueType& Get() { return value; }
inline void operator()(const ValueType& newValue) { Set(newValue); }
inline const ValueType& operator()() { return Get(); }
inline operator ValueType() { return Get(); }
};
template<typename t> class EnableProperties {
protected:
typedef T PropertyFriendClass;
};
#define Property(Access, type) class : public Access##Property<type , PropertyFriendClass> {}
#define CustomProperty(Access, type) class : public Access##Property<type , PropertyFriendClass>
#define Setter virtual void Set(const ValueType& value)
#define Getter virtual const ValueType& Get()