Last active
May 14, 2023 17:36
-
-
Save Arkanosis/632240 to your computer and use it in GitHub Desktop.
Python style properties in C++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
** 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