Skip to content

Instantly share code, notes, and snippets.

@ecatmur
Created April 5, 2022 22:29
Show Gist options
  • Save ecatmur/eb6590bcd53d4ec0c082d03153950c45 to your computer and use it in GitHub Desktop.
Save ecatmur/eb6590bcd53d4ec0c082d03153950c45 to your computer and use it in GitHub Desktop.
#include <type_traits>
template<class, auto, auto, auto>
class accessor;
template<class C, auto id, auto getter, auto setter>
class property : public decltype(
id.template operator()<accessor<C, id, getter, setter>>())::type {};
template<class C, auto id, auto getter, auto setter>
class accessor {
private:
using P = property<C, id, getter, setter>;
C& self() { return *static_cast<C*>(reinterpret_cast<P*>(this)); }
C const& self() const { return *static_cast<C const*>(reinterpret_cast<P const*>(this)); }
public:
decltype(auto) get() { return getter(self()); }
decltype(auto) get() const { return getter(self()); }
operator decltype(auto)() { return get(); }
operator decltype(auto)() const { return get(); }
decltype(auto) operator=(auto value) { return setter(self(), value); }
};
#define ID(id) []<class T> { struct B { T id; }; return std::type_identity<B>(); }
#define PROPERTY(C, id, getter, setter) \
property<C, ID(id), getter, setter>
#include <chrono>
#include <string>
class Person :
public PROPERTY(Person, name,
[](auto const& self) { return self.mName; },
[](auto& self, auto name) { self.mName = name; }),
public PROPERTY(Person, age,
[](auto const& self) { return self.mAge; },
[](auto& self, auto age) { self.mAge = age; })
{
private:
std::string mName;
std::chrono::years mAge;
};
#include <iostream>
int main() {
Person p;
p.name = "Fred";
p.age = std::chrono::years(22);
std::cout << "Happy " << p.age.get() << " birthday, " << p.name.get() << "!" << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment