#include <iostream>
#include <string>
#include <typeinfo>

#ifdef __GNUG__ // GCC

#include <cxxabi.h>
#include <cstdlib>

static std::string readable_name( const char* mangled_name )
{
    int status ;
    char* temp = __cxxabiv1::__cxa_demangle( mangled_name, nullptr, nullptr, &status ) ;
    if(temp)
    {
        std::string result(temp) ;
        std::free(temp) ;
        return result ;
    }
    else return mangled_name ;
}

#else // not GCC

std::string readable_name( const char* mangled_name ) { return mangled_name ; }

#endif // __GNUG__

template < typename T > std::string type_to_string()
{ return readable_name( typeid(T).name() ) ; }

template < typename T > std::string type_to_string( const T& obj )
{ return readable_name( typeid(obj).name() ) ; }

#include <vector>

int main()
{
    std::vector<std::string> seq ;

    std::cout << type_to_string( 1234 ) << '\n'
               << type_to_string( std::realloc ) << '\n'
               << type_to_string( std::cout ) << '\n'
               << type_to_string( std::cin.rdbuf() ) << '\n'
               << type_to_string( *std::cin.rdbuf() ) << '\n'
               << type_to_string( std::string::npos ) << '\n'
               << type_to_string<std::string::iterator>() << '\n'
               << type_to_string( seq ) << '\n'
               << type_to_string( seq.size() ) << '\n'
               << type_to_string< decltype( std::srand(9) ) >() << '\n' ;
}
