#include <iostream>
struct low_priority {};
struct high_priority : low_priority {};
struct highest_priority : high_priority {};
template<typename T>
class Mixin
{
private:
template<typename T2>
static auto CallImpl( highest_priority const& ) -> decltype( T2::SomeFunc(), void() )
{
std::cout << "1\n";
T::SomeFunc();
}
template<typename T2>
static auto CallImpl( high_priority const& ) -> decltype( T2{}.SomeFunc(), void() )
{
std::cout << "2\n";
T{}.SomeFunc();
}
template<typename T2>
void CallImpl( low_priority const& )
{
std::cout << "3\n";
DefaultImpl();
}
public:
void Call()
{
CallImpl<T>(highest_priority{});
}
void DefaultImpl()
{
std::cout << "Mixin::DefaultImpl\n";
}
};
struct A
{
static void SomeFunc()
{
std::cout << "A::SomeFunc()\n";
}
};
struct C
{
void SomeFunc()
{
std::cout << "C::SomeFunc()\n";
}
};
struct B {};
int main()
{
Mixin<A>{}.Call();
Mixin<B>{}.Call();
Mixin<C>{}.Call();
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKc3RydWN0IGxvd19wcmlvcml0eSB7fTsKc3RydWN0IGhpZ2hfcHJpb3JpdHkgOiBsb3dfcHJpb3JpdHkge307CnN0cnVjdCBoaWdoZXN0X3ByaW9yaXR5IDogaGlnaF9wcmlvcml0eSB7fTsKCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CmNsYXNzIE1peGluCnsKcHJpdmF0ZToKCiAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBUMj4KICAgIHN0YXRpYyBhdXRvIENhbGxJbXBsKCBoaWdoZXN0X3ByaW9yaXR5IGNvbnN0JiApIC0+IGRlY2x0eXBlKCBUMjo6U29tZUZ1bmMoKSwgdm9pZCgpICkKICAgIHsKICAgIAlzdGQ6OmNvdXQgPDwgIjFcbiI7CiAgICAgICAgVDo6U29tZUZ1bmMoKTsKICAgIH0KCiAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBUMj4KICAgIHN0YXRpYyBhdXRvIENhbGxJbXBsKCBoaWdoX3ByaW9yaXR5IGNvbnN0JiApIC0+IGRlY2x0eXBlKCBUMnt9LlNvbWVGdW5jKCksIHZvaWQoKSApCiAgICB7CiAgICAJc3RkOjpjb3V0IDw8ICIyXG4iOwogICAgICAgIFR7fS5Tb21lRnVuYygpOwogICAgfQoKICAgIHRlbXBsYXRlPHR5cGVuYW1lIFQyPgogICAgdm9pZCBDYWxsSW1wbCggbG93X3ByaW9yaXR5IGNvbnN0JiApCiAgICB7CiAgICAJc3RkOjpjb3V0IDw8ICIzXG4iOwogICAgICAgIERlZmF1bHRJbXBsKCk7CiAgICB9CgpwdWJsaWM6CgogICAgdm9pZCBDYWxsKCkKICAgIHsKICAgICAgICBDYWxsSW1wbDxUPihoaWdoZXN0X3ByaW9yaXR5e30pOwogICAgfQoKICAgdm9pZCBEZWZhdWx0SW1wbCgpCiAgIHsKICAgICAgICBzdGQ6OmNvdXQgPDwgIk1peGluOjpEZWZhdWx0SW1wbFxuIjsKICAgfQp9OwoKc3RydWN0IEEKewogICBzdGF0aWMgdm9pZCBTb21lRnVuYygpCiAgIHsKICAgICAgICBzdGQ6OmNvdXQgPDwgIkE6OlNvbWVGdW5jKClcbiI7CiAgIH0KfTsKCnN0cnVjdCBDCnsKICAgdm9pZCBTb21lRnVuYygpCiAgIHsKICAgICAgICBzdGQ6OmNvdXQgPDwgIkM6OlNvbWVGdW5jKClcbiI7CiAgIH0KfTsKCnN0cnVjdCBCIHt9OwoKaW50IG1haW4oKQp7CiAgICBNaXhpbjxBPnt9LkNhbGwoKTsKICAgIE1peGluPEI+e30uQ2FsbCgpOwogICAgTWl4aW48Qz57fS5DYWxsKCk7Cn0K