Skip to content

Instantly share code, notes, and snippets.

@mpapierski
Created February 25, 2012 02:30
Show Gist options
  • Save mpapierski/1905395 to your computer and use it in GitHub Desktop.
Save mpapierski/1905395 to your computer and use it in GitHub Desktop.
Properties with getter/setter function calls
// Properties with getter/setter function calls
//
// Copyright 2011 Michał Papierski <michal@papierski.net>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
// MA 02110-1301, USA.
#include <iostream>
#include <cassert>
using namespace std;
struct Observable { };
template <typename var_type, typename T, var_type (T::*Getter)() = 0, void (T::*Setter)(var_type) = 0>
class Property
{
public:
typedef var_type variable_t;
typedef variable_t (Observable::*GetterType)();
typedef void (Observable::*SetterType)(variable_t);
private:
GetterType m_Getter; /* Getter function */
SetterType m_Setter; /* Setter function */
Observable* m_Owner; /* Owner */
public:
Property(Observable* obj):
m_Getter(reinterpret_cast<GetterType>(Getter)),
m_Setter(reinterpret_cast<SetterType>(Setter)),
m_Owner(obj)
{
}
/* Call getter */
variable_t value()
{
return ((*m_Owner).*m_Getter)();
}
/* Call setter */
void setValue(variable_t value)
{
(m_Owner->*m_Setter)(value);
}
/* Call setter */
Property& operator=(variable_t value)
{
setValue(value);
return *this;
}
bool operator==(variable_t value)
{
return this->value() == value;
}
/* Cast op */
operator variable_t()
{
return value();
}
};
/* Ugly macros */
#define CLASS(class_name, ...)\
class class_name: public Observable, ## __VA_ARGS__ \
{\
private:\
typedef class_name object_type_for_property;\
public:\
static string getClassName() { return #class_name; }
#define PROPERTY(var_type, getter, setter) Property<var_type, object_type_for_property, &object_type_for_property::getter, &object_type_for_property::setter>
#define DEFAULT_PROPERTY(classname, var_type, var_name) \
var_type m_##var_name;\
var_type get##var_name() \
{\
return m_##var_name;\
}\
void set##var_name(var_type var_name)\
{\
this->m_##var_name = var_name;\
}\
Property<var_type, classname, &classname::get##var_name, &classname::set##var_name> var_name;
class Object: public Observable
{
public:
DEFAULT_PROPERTY(Object, int, X)
DEFAULT_PROPERTY(Object, int, Y)
Object(): X(this), Y(this)
{
}
};
int main(int argc, char* argv[])
{
Object obj;
obj.X = 69;
obj.Y = 79;
assert(obj.X == 69);
assert(obj.Y == 79);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment