#include <type_traits>
template <typename> struct IsBase : std::false_type {};
template <typename Self>
struct Base {
Base& operator()() {
return *this;
};
template <typename Other,
typename = typename std::enable_if<std::is_same<Other, Self>::value ||
IsBase<Other>::value>::type>
Self operator+(const Other& other) const {
return static_cast<const Self&>(*this);
}
};
template <typename X> struct IsBase<Base<X>> : std::true_type {};
struct D1 : Base<D1> {};
struct D2 : Base<D2> {};
int main() {
D1 d1;
D2 d2;
d1 + d1;
d2 + d2;
d1() + d2();
d1 + d2;
}
I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgoKdGVtcGxhdGUgPHR5cGVuYW1lPiBzdHJ1Y3QgSXNCYXNlIDogc3RkOjpmYWxzZV90eXBlIHt9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFNlbGY+CnN0cnVjdCBCYXNlIHsKICAgIEJhc2UmIG9wZXJhdG9yKCkoKSB7CiAgICAgICAgcmV0dXJuICp0aGlzOwogICAgfTsKCiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgT3RoZXIsCiAgICAgICAgICAgICAgdHlwZW5hbWUgPSB0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjxzdGQ6OmlzX3NhbWU8T3RoZXIsIFNlbGY+Ojp2YWx1ZSB8fAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSXNCYXNlPE90aGVyPjo6dmFsdWU+Ojp0eXBlPgogICAgU2VsZiBvcGVyYXRvcisoY29uc3QgT3RoZXImIG90aGVyKSBjb25zdCB7CiAgICAgICAgcmV0dXJuIHN0YXRpY19jYXN0PGNvbnN0IFNlbGYmPigqdGhpcyk7CiAgICB9Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgWD4gc3RydWN0IElzQmFzZTxCYXNlPFg+PiA6IHN0ZDo6dHJ1ZV90eXBlIHt9OwoKCnN0cnVjdCBEMSA6IEJhc2U8RDE+IHt9OwpzdHJ1Y3QgRDIgOiBCYXNlPEQyPiB7fTsKCgppbnQgbWFpbigpIHsKICAgIEQxIGQxOwogICAgRDIgZDI7CiAgICBkMSArIGQxOwogICAgZDIgKyBkMjsKICAgIGQxKCkgKyBkMigpOwogICAgZDEgKyBkMjsKfQoK