#include <tuple>
#include <string>
template <typename... Ts>
class Relations;
namespace std
{
template <std::size_t I, typename... Ts>
auto get(Relations<Ts...>& r)
-> typename std::tuple_element<I, std::tuple<Ts...>>::type&;
}
template <typename A1, typename A2, size_t ind1, size_t ind2>
class Association
{
public:
virtual ~Association()
{
if (!this->empty())
{
this->clear_associations();
}
}
void associate(A2* ref)
{
if (!this->empty() && _ref == ref)
{
return;
}
if (_ref)
{
std::get<ind2>(*_ref).reset_association();
}
_ref = ref;
std::get<ind2>(*ref).associate(static_cast<A1*>(this));
};
void associate(A2& ref)
{
this->associate(&ref);
};
bool empty() const
{
if (!_ref)
return true;
else
return false;
}
void remove_association(A2* ref)
{
if (_ref == ref)
{
this->reset_association();
std::get<ind2>(*ref).remove_association(static_cast<A1*>(this));
}
}
void remove_association(A2& ref)
{
this->remove_association(&ref);
}
void reset_association()
{
_ref = 0;
}
void clear_associations()
{
if (_ref)
{
std::get<ind2>(*_ref).remove_association(static_cast<A1*>(this));
}
this->reset_association();
}
A2* get_association() const
{
return _ref;
}
private:
A2* _ref=0;
};
template <typename... Ts>
class Relations : public Ts...
{
public:
Relations() {}
virtual ~Relations() {}
};
namespace std
{
template <std::size_t I, typename... Ts>
auto get(Relations<Ts...>& r)
-> typename std::tuple_element<I, std::tuple<Ts...>>::type&
{
return static_cast<typename std::tuple_element<I, std::tuple<Ts...>>::type&>(r);
}
}
class J;
class K;
class I : public Relations<Association<I, J, 0, 0>, Association<I, K, 1, 0>>
{
public:
std::string type="I";
};
class J : public Relations<Association<J, I, 0, 0>>
{
public:
std::string type="J";
};
class K : public Relations<Association<K, I, 0, 1>>
{
public:
std::string type="K";
};
int main()
{
I i;
J j;
K k;
std::get<0>(i).associate(j);
return 0;
}
I2luY2x1ZGUgPHR1cGxlPgojaW5jbHVkZSA8c3RyaW5nPgoKdGVtcGxhdGUgPHR5cGVuYW1lLi4uIFRzPgpjbGFzcyBSZWxhdGlvbnM7CgpuYW1lc3BhY2Ugc3RkCnsKCXRlbXBsYXRlIDxzdGQ6OnNpemVfdCBJLCB0eXBlbmFtZS4uLiBUcz4KCWF1dG8gZ2V0KFJlbGF0aW9uczxUcy4uLj4mIHIpCgktPiB0eXBlbmFtZSBzdGQ6OnR1cGxlX2VsZW1lbnQ8SSwgc3RkOjp0dXBsZTxUcy4uLj4+Ojp0eXBlJjsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIEExLCB0eXBlbmFtZSBBMiwgc2l6ZV90IGluZDEsIHNpemVfdCBpbmQyPgpjbGFzcyBBc3NvY2lhdGlvbgp7CnB1YmxpYzoKICAgIHZpcnR1YWwgfkFzc29jaWF0aW9uKCkKICAgIHsKICAgICAgICBpZiAoIXRoaXMtPmVtcHR5KCkpCiAgICAgICAgewogICAgICAgICAgICB0aGlzLT5jbGVhcl9hc3NvY2lhdGlvbnMoKTsKICAgICAgICB9CiAgICB9CgogICAgdm9pZCBhc3NvY2lhdGUoQTIqIHJlZikKICAgIHsKICAgICAgICBpZiAoIXRoaXMtPmVtcHR5KCkgJiYgX3JlZiA9PSByZWYpCiAgICAgICAgewogICAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBpZiAoX3JlZikKICAgICAgICB7CiAgICAgICAgICAgIHN0ZDo6Z2V0PGluZDI+KCpfcmVmKS5yZXNldF9hc3NvY2lhdGlvbigpOwogICAgICAgIH0KCiAgICAgICAgX3JlZiA9IHJlZjsKICAgICAgICBzdGQ6OmdldDxpbmQyPigqcmVmKS5hc3NvY2lhdGUoc3RhdGljX2Nhc3Q8QTEqPih0aGlzKSk7CiAgICB9OwoKICAgIHZvaWQgYXNzb2NpYXRlKEEyJiByZWYpCiAgICB7CiAgICAgICAgdGhpcy0+YXNzb2NpYXRlKCZyZWYpOwogICAgfTsKCiAgICBib29sIGVtcHR5KCkgY29uc3QKICAgIHsKICAgICAgICBpZiAoIV9yZWYpCiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIGVsc2UKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQoKICAgIHZvaWQgcmVtb3ZlX2Fzc29jaWF0aW9uKEEyKiByZWYpCiAgICB7CiAgICAgICAgaWYgKF9yZWYgPT0gcmVmKQogICAgICAgIHsKICAgICAgICAgICAgdGhpcy0+cmVzZXRfYXNzb2NpYXRpb24oKTsKICAgICAgICAgICAgc3RkOjpnZXQ8aW5kMj4oKnJlZikucmVtb3ZlX2Fzc29jaWF0aW9uKHN0YXRpY19jYXN0PEExKj4odGhpcykpOwogICAgICAgIH0KICAgIH0KCiAgICB2b2lkIHJlbW92ZV9hc3NvY2lhdGlvbihBMiYgcmVmKQogICAgewogICAgICAgIHRoaXMtPnJlbW92ZV9hc3NvY2lhdGlvbigmcmVmKTsKICAgIH0KCiAgICB2b2lkIHJlc2V0X2Fzc29jaWF0aW9uKCkKICAgIHsKICAgICAgICBfcmVmID0gMDsKICAgIH0KCiAgICB2b2lkIGNsZWFyX2Fzc29jaWF0aW9ucygpCiAgICB7CiAgICAgICAgaWYgKF9yZWYpCiAgICAgICAgewogICAgICAgICAgICBzdGQ6OmdldDxpbmQyPigqX3JlZikucmVtb3ZlX2Fzc29jaWF0aW9uKHN0YXRpY19jYXN0PEExKj4odGhpcykpOwogICAgICAgIH0KICAgICAgICB0aGlzLT5yZXNldF9hc3NvY2lhdGlvbigpOwogICAgfQoKICAgIEEyKiBnZXRfYXNzb2NpYXRpb24oKSBjb25zdAogICAgewogICAgICAgIHJldHVybiBfcmVmOwogICAgfQoKcHJpdmF0ZToKICAgIEEyKiBfcmVmPTA7Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUuLi4gVHM+CmNsYXNzIFJlbGF0aW9ucyA6IHB1YmxpYyBUcy4uLgp7CnB1YmxpYzoKICAgIFJlbGF0aW9ucygpIHt9CiAgICB2aXJ0dWFsIH5SZWxhdGlvbnMoKSB7fQp9OwoKbmFtZXNwYWNlIHN0ZAp7Cgl0ZW1wbGF0ZSA8c3RkOjpzaXplX3QgSSwgdHlwZW5hbWUuLi4gVHM+CglhdXRvIGdldChSZWxhdGlvbnM8VHMuLi4+JiByKQoJLT4gdHlwZW5hbWUgc3RkOjp0dXBsZV9lbGVtZW50PEksIHN0ZDo6dHVwbGU8VHMuLi4+Pjo6dHlwZSYKCXsKCQlyZXR1cm4gc3RhdGljX2Nhc3Q8dHlwZW5hbWUgc3RkOjp0dXBsZV9lbGVtZW50PEksIHN0ZDo6dHVwbGU8VHMuLi4+Pjo6dHlwZSY+KHIpOwoJfQp9CgpjbGFzcyBKOwpjbGFzcyBLOwoKY2xhc3MgSSA6IHB1YmxpYyBSZWxhdGlvbnM8QXNzb2NpYXRpb248SSwgSiwgMCwgMD4sIEFzc29jaWF0aW9uPEksIEssIDEsIDA+Pgp7CnB1YmxpYzoKICAgIHN0ZDo6c3RyaW5nIHR5cGU9IkkiOwp9OwoKY2xhc3MgSiA6IHB1YmxpYyBSZWxhdGlvbnM8QXNzb2NpYXRpb248SiwgSSwgMCwgMD4+CnsKcHVibGljOgogICAgc3RkOjpzdHJpbmcgdHlwZT0iSiI7Cn07CgpjbGFzcyBLIDogcHVibGljIFJlbGF0aW9uczxBc3NvY2lhdGlvbjxLLCBJLCAwLCAxPj4KewpwdWJsaWM6CiAgICBzdGQ6OnN0cmluZyB0eXBlPSJLIjsKfTsKCmludCBtYWluKCkKewogICAgSSBpOwogICAgSiBqOwogICAgSyBrOwogICAgc3RkOjpnZXQ8MD4oaSkuYXNzb2NpYXRlKGopOwoKICAgIHJldHVybiAwOwp9