Навеяно статьей Property в C++
За пять минут размышлений, как обойтись без директив препроцессора, появилось нечто…
Может ли это «нечто» быть полезным, осмысливать лень. Есть масса недостатков, нет доступа по имени, зато без макросов )
up: геттер-сеттер — сделаны методами класса
За пять минут размышлений, как обойтись без директив препроцессора, появилось нечто…
Может ли это «нечто» быть полезным, осмысливать лень. Есть масса недостатков, нет доступа по имени, зато без макросов )
up: геттер-сеттер — сделаны методами класса
#include <string>
#include <map>
#include <iostream>
using namespace std;
template<class B,class T> class DefineProperty
{
T value;
B *that;
typedef void (B::*SetterPtr)(const T&);
typedef T (B::*GetterPtr)(const T&) const;
void (B::*setter)( const T &val );
T (B::*getter)( const T &val ) const;
public:
DefineProperty()
{
setter = NULL;
getter = NULL;
that = NULL;
}
DefineProperty(B *self, GetterPtr get, SetterPtr set)
{
that = self;
setter = set;
getter = get;
}
DefineProperty(B *self, SetterPtr set, GetterPtr get)
{
that = self;
setter = set;
getter = get;
}
DefineProperty(B *self, GetterPtr get)
{
that = self;
setter = NULL;
getter = get;
}
DefineProperty(B *self, SetterPtr set)
{
that = self;
setter = set;
getter = NULL;
}
void operator = ( const T &val )
{
set( val );
}
void set( const T &val )
{
value = val;
if( setter )
(that->*setter)( val );
}
operator T () const
{
return get();
}
T get() const
{
if( getter )
return (that->*getter)(value);
return value;
}
T field_get() const
{
return value;
}
void field_set( const T &val )
{
value = val;
}
};
template<class T,class B>
std::ostream& operator<<(std::ostream &out, const DefineProperty<T,B> &val)
{
out << (val.get());
return out;
}
class ClassWithProps
{
public:
DefineProperty<ClassWithProps,int> Integer;
DefineProperty<ClassWithProps,int> PlainInteger;
DefineProperty<ClassWithProps,int> FakedInteger;
DefineProperty<ClassWithProps,string> String;
// Disable warning 4355 - use this pointer in ctor
// There is no violation in this particular case
#pragma warning( push )
#pragma warning( disable: 4355 )
ClassWithProps()
// Getter-Setter declaration
: Integer(this, &ClassWithProps::IntegerSetter),
FakedInteger(this, &ClassWithProps::IntegerGetter),
String(this, &ClassWithProps::StringGetter, &ClassWithProps::StringSetter)
{
}
#pragma warning( pop )
private:
void IntegerSetter( const int &value )
{
cout << "Set(" << value << ")" << endl;
Integer.field_set(value+1);
}
int IntegerGetter( const int &value ) const
{
return value * 2;
}
string StringGetter( const string &value ) const
{
return "I love " + value;
}
void StringSetter( const string &value )
{
}
};
int main(int argc, char* argv[])
{
ClassWithProps props;
// not getter/setter
props.PlainInteger = 1;
int plain = props.PlainInteger;
// only setter
props.Integer = 100;
int real = props.Integer;
// only getter
props.FakedInteger = 100;
int faked = props.FakedInteger;
// getter and setter
props.String = "habr";
string str = props.String;
// allow to use ostream
cout << "Faked integer = " << props.FakedInteger << endl;
cout << props.String << endl;
return 0;
}