//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));
}
