#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;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3RyaW5nPgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKdGVtcGxhdGUgPGNsYXNzIEEsIGNsYXNzIEI+CnZvaWQgZm9vX2ltcChBJiBhLCBCJiBiLCBsb25nIHgpCnsKCWNvdXQgPDwgImdlbmVyaWMgZmFsbGJhY2siIDw8IGVuZGw7Cn0KCnRlbXBsYXRlIDxjbGFzcyBBPgp2b2lkIGZvb19pbXAoQSYgYSwgaW50JiBpLCBsb25nIHgpCnsKCWNvdXQgPDwgImdlbmVyaWMgaW50IiA8PCBlbmRsOwp9Cgp0ZW1wbGF0ZSA8Y2xhc3MgQT4Kdm9pZCBmb29faW1wKEEmIGEsIHN0cmluZyYgcywgbG9uZyB4KQp7Cgljb3V0IDw8ICJnZW5lcmljIHN0ciIgPDwgZW5kbDsKfQoKc3RydWN0IG1pbmUKewoJaW50IGlzX3NwZWNpYWw7Cn07Cgp0ZW1wbGF0ZSA8Y2xhc3MgQSwgY2xhc3MgQj4KYXV0byBmb29faW1wKEEmIGEsIEImIGIsIGludCB4KSAtPiBkZWNsdHlwZShBOjppc19zcGVjaWFsLCB2b2lkKCkpCnsKCWNvdXQgPDwgInNwZWNpYWxpemVkIGZhbGxiYWNrIiA8PCBlbmRsOwp9Cgp0ZW1wbGF0ZSA8Y2xhc3MgQSwgY2xhc3MgQj4KYXV0byBmb28oQSYgYSwgQiYgYikgLT4gZGVjbHR5cGUoZm9vX2ltcChhLCBiLCAwKSwgdm9pZCgpKQp7Cglmb29faW1wKGEsIGIsIDApOwp9CgppbnQgbWFpbigpIHsKCWludCB4OwoJc3RyaW5nIHk7CglmbG9hdCB6OwoJc3RyaW5nIGdlbmVyaWM7CgltaW5lIHNwZWNpYWw7CgkKCWZvbyhnZW5lcmljLCB4KTsKCWZvbyhnZW5lcmljLCB5KTsKCWZvbyhnZW5lcmljLCB6KTsKCWZvbyhzcGVjaWFsLCB4KTsKCWZvbyhzcGVjaWFsLCB5KTsKCWZvbyhzcGVjaWFsLCB6KTsKCQoJcmV0dXJuIDA7Cn0=