#include struct property0 {}; struct property1 {}; struct property2 {}; template property0 get_prop(type*); char id(property0); char (&id(property1))[2]; char (&id(property2))[3]; template struct _impl; template<> struct _impl<1> { typedef property0 type; }; template<> struct _impl<2> { typedef property1 type; }; template<> struct _impl<3> { typedef property2 type; }; template struct prop { typedef typename _impl::type type; }; template::type> struct expression { friend property get_prop(type*) { return property(); } }; struct s : public expression {}; struct s1 : public expression {}; struct s2 : public expression {}; template void foo(const expression&) { typedef typename prop::type associated_property; std::cout << "foo: " << typeid(associated_property).name() << "\n"; return; } template void bar(const expression&) {} int main() { foo(s()); foo(s1()); foo(s2()); //bar(s()); //should not compile //bar(s1()); //should not compile bar(s2()); return 0; }