#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();
}
