//Refer to: http://m...content-available-to-author-only...y.com/2013/06/03/overriding-the-broken-universal-reference-t/
#include <iostream>
#include <type_traits>
template<typename T>
struct class_tag { };
template<typename TF>
void apply( TF && f ) {
//get the unqualified type for the purpose of tagging
class_tag<typename std::decay<TF>::type> tag;
apply_impl( std::forward<TF>(f), tag );
}
template<typename TF, typename Tag>
void apply_impl( TF && f, Tag ) {
std::cout << f << std::endl;
}
struct match_a { };
template<typename TF>
void apply_impl( TF && f, class_tag<match_a> ) {
std::cout << "match_a" << std::endl;
}
struct match_b { };
template<typename TF>
void apply_impl( TF && f, class_tag<match_b> ) {
std::cout << "match_b" << std::endl;
}
template<typename TF>
void apply_impl( TF && f, class_tag<int*> ) {
std::cout << "int*" << std::endl;
}
int main() {
apply( 12 );
apply( "hello" );
apply( match_a() );
apply( match_b() );
match_a a;
apply(a);
apply( static_cast<match_a const&>(a) );
apply( static_cast<match_a const>(a) );
int b[5];
apply(b);
apply(static_cast<int*>(b));
}
Ly9SZWZlciB0bzogaHR0cDovL20uLi5jb250ZW50LWF2YWlsYWJsZS10by1hdXRob3Itb25seS4uLnkuY29tLzIwMTMvMDYvMDMvb3ZlcnJpZGluZy10aGUtYnJva2VuLXVuaXZlcnNhbC1yZWZlcmVuY2UtdC8KI2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgpzdHJ1Y3QgY2xhc3NfdGFnIHsgfTsKCnRlbXBsYXRlPHR5cGVuYW1lIFRGPgp2b2lkIGFwcGx5KCBURiAmJiBmICkgewogICAgLy9nZXQgdGhlIHVucXVhbGlmaWVkIHR5cGUgZm9yIHRoZSBwdXJwb3NlIG9mIHRhZ2dpbmcKCWNsYXNzX3RhZzx0eXBlbmFtZSBzdGQ6OmRlY2F5PFRGPjo6dHlwZT4gdGFnOwoJYXBwbHlfaW1wbCggc3RkOjpmb3J3YXJkPFRGPihmKSwgdGFnICk7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFRGLCB0eXBlbmFtZSBUYWc+CnZvaWQgYXBwbHlfaW1wbCggVEYgJiYgZiwgVGFnICkgewogCXN0ZDo6Y291dCA8PCBmIDw8IHN0ZDo6ZW5kbDsKIH0KCnN0cnVjdCBtYXRjaF9hIHsgfTsKdGVtcGxhdGU8dHlwZW5hbWUgVEY+IAp2b2lkIGFwcGx5X2ltcGwoIFRGICYmIGYsIGNsYXNzX3RhZzxtYXRjaF9hPiApIHsKCXN0ZDo6Y291dCA8PCAibWF0Y2hfYSIgPDwgc3RkOjplbmRsOwp9CgpzdHJ1Y3QgbWF0Y2hfYiB7IH07CnRlbXBsYXRlPHR5cGVuYW1lIFRGPgp2b2lkIGFwcGx5X2ltcGwoIFRGICYmIGYsIGNsYXNzX3RhZzxtYXRjaF9iPiApIHsKCXN0ZDo6Y291dCA8PCAibWF0Y2hfYiIgPDwgc3RkOjplbmRsOwp9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBURj4Kdm9pZCBhcHBseV9pbXBsKCBURiAmJiBmLCBjbGFzc190YWc8aW50Kj4gKSB7CglzdGQ6OmNvdXQgPDwgImludCoiIDw8IHN0ZDo6ZW5kbDsKfQoKaW50IG1haW4oKSB7CQoJYXBwbHkoIDEyICk7CglhcHBseSggImhlbGxvIiApOwoJYXBwbHkoIG1hdGNoX2EoKSApOwoJYXBwbHkoIG1hdGNoX2IoKSApOwoJCgltYXRjaF9hIGE7CglhcHBseShhKTsKCWFwcGx5KCBzdGF0aWNfY2FzdDxtYXRjaF9hIGNvbnN0Jj4oYSkgKTsKCWFwcGx5KCBzdGF0aWNfY2FzdDxtYXRjaF9hIGNvbnN0PihhKSApOwoJCglpbnQgYls1XTsKCWFwcGx5KGIpOwoJYXBwbHkoc3RhdGljX2Nhc3Q8aW50Kj4oYikpOwp9Cg==