Skip to content

Instantly share code, notes, and snippets.

@Arkanosis
Last active May 14, 2023 17:36
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Arkanosis/632240 to your computer and use it in GitHub Desktop.
Save Arkanosis/632240 to your computer and use it in GitHub Desktop.
Python style properties in C++
/*
** Python style properties in C++
** (C) 2010 Arkanosis
** jroquet@arkanosis.net
**
** Example code released under the MIT license
** http://www.opensource.org/licenses/mit-license.php
**
** This is an original portable version of
** http://www.codeproject.com/KB/cpp/properties.aspx
** which only worked under MSVC
*/
/*
** This is the Python-like version, for the C#-like version, see:
** http://gist.github.com/632294
*/
#include <iostream>
/************************************************************
** This is where the magic goes
*************************************************************/
template <typename ClassT, typename TypeT, TypeT (ClassT::*Getter)() const>
class _Get
{
public:
explicit _Get(ClassT const* self)
: _this(self) {
}
inline operator TypeT() const
{
return (_this->*Getter)();
}
private:
TypeT operator=(TypeT value) const;
private:
ClassT const* _this;
};
template <typename ClassT, typename TypeT, void (ClassT::*Setter)(TypeT)>
class _Set
{
public:
explicit _Set(ClassT* self)
: _this(self) {
}
inline TypeT operator=(TypeT value) const
{
(_this->*Setter)(value);
return value;
}
private:
operator TypeT() const;
private:
ClassT* _this;
};
template <typename ClassT, typename TypeT, TypeT (ClassT::*Getter)() const, void (ClassT::*Setter)(TypeT)>
class _GetSet
{
public:
explicit _GetSet(ClassT* self)
: _this(self) {
}
inline operator TypeT() const
{
return (_this->*Getter)();
}
inline TypeT operator=(TypeT value) const
{
(_this->*Setter)(value);
return value;
}
private:
ClassT* _this;
};
#define RO_PROPERTY(CLASS, TYPE, GETTER) _Get<CLASS, TYPE, &CLASS::GETTER>
#define WO_PROPERTY(CLASS, TYPE, SETTER) _Set<CLASS, TYPE, &CLASS::SETTER>
#define RW_PROPERTY(CLASS, TYPE, GETTER, SETTER) _GetSet<CLASS, TYPE, &CLASS::GETTER, &CLASS::SETTER>
/************************************************************
** End of magic, now demo!
*************************************************************/
class MyClass
{
private:
int _attribute;
public:
inline int getAttribute() const {
std::clog << "Getting attribute equals to " << _attribute << std::endl;
return _attribute;
}
inline void setAttribute(int value) {
std::clog << "Setting attribute to " << value << std::endl;
_attribute = value;
}
RO_PROPERTY(MyClass, int, getAttribute) readOnlyProperty;
WO_PROPERTY(MyClass, int, setAttribute) writeOnlyProperty;
RW_PROPERTY(MyClass, int, getAttribute, setAttribute) readWriteProperty;
MyClass()
: _attribute(0),
readOnlyProperty(this),
writeOnlyProperty(this),
readWriteProperty(this) {
}
};
int main()
{
MyClass myVar;
// Read only
std::cout << myVar.readOnlyProperty << std::endl; // OK
//myVar.readOnlyProperty = 42; // Will fail
// Write only
//std::cout << myVar.writeOnlyProperty << std::endl; // Will fail
myVar.writeOnlyProperty = 42; // OK
// Read write
std::cout << myVar.readWriteProperty << std::endl; // OK
myVar.readWriteProperty = 42; // OK
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment