#include <iostream>
#include <string>
using namespace std;

template <class A, class B>
void foo_imp(A& a, B& b, long x)
{
	cout << "generic fallback" << endl;
}

template <class A>
void foo_imp(A& a, int& i, long x)
{
	cout << "generic int" << endl;
}

template <class A>
void foo_imp(A& a, string& s, long x)
{
	cout << "generic str" << endl;
}

struct mine
{
	int is_special;
};

template <class A, class B>
auto foo_imp(A& a, B& b, int x) -> decltype(A::is_special, void())
{
	cout << "specialized fallback" << endl;
}

template <class A, class B>
auto foo(A& a, B& b) -> decltype(foo_imp(a, b, 0), void())
{
	foo_imp(a, b, 0);
}

int main() {
	int x;
	string y;
	float z;
	string generic;
	mine special;
	
	foo(generic, x);
	foo(generic, y);
	foo(generic, z);
	foo(special, x);
	foo(special, y);
	foo(special, z);
	
	return 0;
}