#include <functional>
#include <iostream>
template<typename T>
struct property
{
public:
typedef std::function<T()> getter;
typedef std::function<void(T)> setter;
public:
property(getter get, setter set)
: get_(get)
, set_(set)
{ }
operator T() const { return get_(); }
property& operator=(T x) { set_(x); return *this; }
private:
getter get_;
setter set_;
};
class Vec2
{
public:
Vec2(int vx, int vy)
: x(std::bind(&Vec2::get_x, this), std::bind(&Vec2::set_x, this, std::placeholders::_1))
, y(std::bind(&Vec2::get_y, this), std::bind(&Vec2::set_y, this, std::placeholders::_1))
, x_(vx)
, y_(vy)
{ }
property<int> x;
property<int> y;
protected:
int get_x() { return x_; }
void set_x(int x) { x_ = x; }
int get_y() { return y_; }
void set_y(int y) { y_ = y; }
private:
int x_, y_;
};
class Vec3
{
public:
Vec3(int vx, int vy, int vz)
: x(std::bind(&Vec3::get_x, this), std::bind(&Vec3::set_x, this, std::placeholders::_1))
, y(std::bind(&Vec3::get_y, this), std::bind(&Vec3::set_y, this, std::placeholders::_1))
, z(std::bind(&Vec3::get_z, this), std::bind(&Vec3::set_z, this, std::placeholders::_1))
, xy(std::bind(&Vec3::get_xy, this), std::bind(&Vec3::set_xy, this, std::placeholders::_1))
, xz(std::bind(&Vec3::get_xz, this), std::bind(&Vec3::set_xz, this, std::placeholders::_1))
, yz(std::bind(&Vec3::get_yz, this), std::bind(&Vec3::set_yz, this, std::placeholders::_1))
, x_(vx)
, y_(vy)
, z_(vz)
{ }
property<int> x;
property<int> y;
property<int> z;
property<Vec2> xy;
property<Vec2> xz;
property<Vec2> yz;
protected:
int get_x() { return x_; }
void set_x(int x) { x_ = x; }
int get_y() { return y_; }
void set_y(int y) { y_ = y; }
int get_z() { return z_; }
void set_z(int z) { z_ = z; }
Vec2 get_xy() { return { x_, y_ }; }
void set_xy(Vec2 xy) { x_ = xy.x; y_ = xy.y; }
Vec2 get_xz() { return { x_, z_ }; }
void set_xz(Vec2 xz) { x_ = xz.x; z_ = xz.y; }
Vec2 get_yz() { return { y_, z_ }; }
void set_yz(Vec2 yz) { y_ = yz.x; z_ = yz.y; }
private:
int x_, y_, z_;
};
std::ostream& operator<<(std::ostream& out, const Vec2& v2)
{
out << '[' << v2.x << ", " << v2.y << ']';
return out;
}
std::ostream& operator<<(std::ostream& out, const Vec3& v3)
{
out << '[' << v3.x << ", " << v3.y << ", " << v3.z << ']';
return out;
}
int main(int argc, char** argv)
{
Vec3 v3 { 2, 0, 1 };
std::cout << v3 << std::endl;
v3.y = 3;
std::cout << v3.xy << std::endl;
std::cout << v3.xz << std::endl;
std::cout << v3.yz << std::endl;
return 0;
}
I2luY2x1ZGUgPGZ1bmN0aW9uYWw+CiNpbmNsdWRlIDxpb3N0cmVhbT4KCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CnN0cnVjdCBwcm9wZXJ0eQp7CnB1YmxpYzoKICB0eXBlZGVmIHN0ZDo6ZnVuY3Rpb248VCgpPiBnZXR0ZXI7CiAgdHlwZWRlZiBzdGQ6OmZ1bmN0aW9uPHZvaWQoVCk+IHNldHRlcjsKCnB1YmxpYzoKICBwcm9wZXJ0eShnZXR0ZXIgZ2V0LCBzZXR0ZXIgc2V0KQogIDogZ2V0XyhnZXQpCiAgLCBzZXRfKHNldCkKICB7IH0KCiAgb3BlcmF0b3IgVCgpIGNvbnN0IHsgcmV0dXJuIGdldF8oKTsgfQogIHByb3BlcnR5JiBvcGVyYXRvcj0oVCB4KSB7IHNldF8oeCk7IHJldHVybiAqdGhpczsgfQoKcHJpdmF0ZToKICBnZXR0ZXIgZ2V0XzsKICBzZXR0ZXIgc2V0XzsKfTsKCmNsYXNzIFZlYzIKewpwdWJsaWM6CiAgVmVjMihpbnQgdngsIGludCB2eSkKICA6IHgoc3RkOjpiaW5kKCZWZWMyOjpnZXRfeCwgdGhpcyksIHN0ZDo6YmluZCgmVmVjMjo6c2V0X3gsIHRoaXMsIHN0ZDo6cGxhY2Vob2xkZXJzOjpfMSkpCiAgLCB5KHN0ZDo6YmluZCgmVmVjMjo6Z2V0X3ksIHRoaXMpLCBzdGQ6OmJpbmQoJlZlYzI6OnNldF95LCB0aGlzLCBzdGQ6OnBsYWNlaG9sZGVyczo6XzEpKQogICwgeF8odngpCiAgLCB5Xyh2eSkKICB7IH0KCiAgcHJvcGVydHk8aW50PiB4OwogIHByb3BlcnR5PGludD4geTsKCnByb3RlY3RlZDoKICBpbnQgZ2V0X3goKSB7IHJldHVybiB4XzsgfQogIHZvaWQgc2V0X3goaW50IHgpIHsgeF8gPSB4OyB9CgogIGludCBnZXRfeSgpIHsgcmV0dXJuIHlfOyB9CiAgdm9pZCBzZXRfeShpbnQgeSkgeyB5XyA9IHk7IH0KCnByaXZhdGU6CiAgaW50IHhfLCB5XzsKfTsKCmNsYXNzIFZlYzMKewpwdWJsaWM6CiAgVmVjMyhpbnQgdngsIGludCB2eSwgaW50IHZ6KQogIDogeChzdGQ6OmJpbmQoJlZlYzM6OmdldF94LCB0aGlzKSwgc3RkOjpiaW5kKCZWZWMzOjpzZXRfeCwgdGhpcywgc3RkOjpwbGFjZWhvbGRlcnM6Ol8xKSkKICAsIHkoc3RkOjpiaW5kKCZWZWMzOjpnZXRfeSwgdGhpcyksIHN0ZDo6YmluZCgmVmVjMzo6c2V0X3ksIHRoaXMsIHN0ZDo6cGxhY2Vob2xkZXJzOjpfMSkpCiAgLCB6KHN0ZDo6YmluZCgmVmVjMzo6Z2V0X3osIHRoaXMpLCBzdGQ6OmJpbmQoJlZlYzM6OnNldF96LCB0aGlzLCBzdGQ6OnBsYWNlaG9sZGVyczo6XzEpKQogICwgeHkoc3RkOjpiaW5kKCZWZWMzOjpnZXRfeHksIHRoaXMpLCBzdGQ6OmJpbmQoJlZlYzM6OnNldF94eSwgdGhpcywgc3RkOjpwbGFjZWhvbGRlcnM6Ol8xKSkKICAsIHh6KHN0ZDo6YmluZCgmVmVjMzo6Z2V0X3h6LCB0aGlzKSwgc3RkOjpiaW5kKCZWZWMzOjpzZXRfeHosIHRoaXMsIHN0ZDo6cGxhY2Vob2xkZXJzOjpfMSkpCiAgLCB5eihzdGQ6OmJpbmQoJlZlYzM6OmdldF95eiwgdGhpcyksIHN0ZDo6YmluZCgmVmVjMzo6c2V0X3l6LCB0aGlzLCBzdGQ6OnBsYWNlaG9sZGVyczo6XzEpKQogICwgeF8odngpCiAgLCB5Xyh2eSkKICAsIHpfKHZ6KQogIHsgfQoKICBwcm9wZXJ0eTxpbnQ+IHg7CiAgcHJvcGVydHk8aW50PiB5OwogIHByb3BlcnR5PGludD4gejsKCiAgcHJvcGVydHk8VmVjMj4geHk7CiAgcHJvcGVydHk8VmVjMj4geHo7CiAgcHJvcGVydHk8VmVjMj4geXo7Cgpwcm90ZWN0ZWQ6CiAgaW50IGdldF94KCkgeyByZXR1cm4geF87IH0KICB2b2lkIHNldF94KGludCB4KSB7IHhfID0geDsgfQoKICBpbnQgZ2V0X3koKSB7IHJldHVybiB5XzsgfQogIHZvaWQgc2V0X3koaW50IHkpIHsgeV8gPSB5OyB9CgogIGludCBnZXRfeigpIHsgcmV0dXJuIHpfOyB9CiAgdm9pZCBzZXRfeihpbnQgeikgeyB6XyA9IHo7IH0KCiAgVmVjMiBnZXRfeHkoKSB7IHJldHVybiB7IHhfLCB5XyB9OyB9CiAgdm9pZCBzZXRfeHkoVmVjMiB4eSkgeyB4XyA9IHh5Lng7IHlfID0geHkueTsgfQoKICBWZWMyIGdldF94eigpIHsgcmV0dXJuIHsgeF8sIHpfIH07IH0KICB2b2lkIHNldF94eihWZWMyIHh6KSB7IHhfID0geHoueDsgel8gPSB4ei55OyB9CgogIFZlYzIgZ2V0X3l6KCkgeyByZXR1cm4geyB5Xywgel8gfTsgfQogIHZvaWQgc2V0X3l6KFZlYzIgeXopIHsgeV8gPSB5ei54OyB6XyA9IHl6Lnk7IH0KCnByaXZhdGU6CiAgaW50IHhfLCB5Xywgel87Cn07CgpzdGQ6Om9zdHJlYW0mIG9wZXJhdG9yPDwoc3RkOjpvc3RyZWFtJiBvdXQsIGNvbnN0IFZlYzImIHYyKQp7CiAgb3V0IDw8ICdbJyA8PCB2Mi54IDw8ICIsICIgPDwgdjIueSA8PCAnXSc7CiAgcmV0dXJuIG91dDsKfQoKc3RkOjpvc3RyZWFtJiBvcGVyYXRvcjw8KHN0ZDo6b3N0cmVhbSYgb3V0LCBjb25zdCBWZWMzJiB2MykKewogIG91dCA8PCAnWycgPDwgdjMueCA8PCAiLCAiIDw8IHYzLnkgPDwgIiwgIiA8PCB2My56IDw8ICddJzsKICByZXR1cm4gb3V0Owp9CgppbnQgbWFpbihpbnQgYXJnYywgY2hhcioqIGFyZ3YpCnsKICBWZWMzIHYzIHsgMiwgMCwgMSB9OwogIHN0ZDo6Y291dCA8PCB2MyA8PCBzdGQ6OmVuZGw7CiAgdjMueSA9IDM7CiAgc3RkOjpjb3V0IDw8IHYzLnh5IDw8IHN0ZDo6ZW5kbDsKICBzdGQ6OmNvdXQgPDwgdjMueHogPDwgc3RkOjplbmRsOwogIHN0ZDo6Y291dCA8PCB2My55eiA8PCBzdGQ6OmVuZGw7CgogIHJldHVybiAwOwp9Cg==