I just coded up the following yet again.
This code works with MinGW g++ and Visual C++, yielding the same result
with both compilers. Since it works with g++ it presumably works also
with clang, at least if the check for __GNUC__ is appropriately modified
(if necessary). And since it works with Visual C++ it presumably also
works with the Intel compiler for Windows.
I'm pretty sure it won't work directly with IBM's compiler, and would be
interested if anyone could post code for that compiler.
<file "demangled.hpp">
#pragma once
// Copyright © 2015 Alf P. Steinbach. Boost license version 1.0.
#include <string>
#include <typeinfo>
#ifdef __GNUC__
# include <cxxabi.h>
#endif
namespace cppx {
using Byte_string = std::string;
#ifdef __GNUC__
inline
auto demangled( char const* const s )
-> Byte_string
{
//
https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a01696.html
int status;
char* const clean_name = abi::__cxa_demangle( s, 0, 0, &status );
auto result = Byte_string( status == 0? clean_name : s );
free( clean_name );
return result;
}
#else
inline
auto demangled( char const* const s )
-> Byte_string
{ return s; }
#endif
} // namespace cppx
</file>
<file "type_name.hpp">
#pragma once
// Copyright © 2015 Alf P. Steinbach. Boost license version 1.0.
#include "demangled.hpp"
#include <stdexcept>
#include <typeinfo>
#include <utility>
#include <iostream>
namespace cppx {
using std::move;
using Byte_string = std::string;
namespace detail {
inline
auto last_word_of( Byte_string s )
-> Byte_string
{
auto const i_last_space = s.rfind( ' ' );
if( i_last_space != Byte_string::npos )
{
return s.substr( i_last_space + 1 );
}
return move( s );
}
}
template< class Type >
auto type_name()
-> Byte_string
{ return detail::last_word_of( demangled( typeid( Type ).name() ) ); }
template< class Type >
auto type_name( Type&& o )
-> Byte_string
{ return detail::last_word_of( demangled( typeid( o ).name() ) ); }
} // namespace cppx
</file>
<file "main.cpp">
#include "type_name.hpp"
#include <iostream>
#include <typeinfo>
using namespace std;
struct My_base { virtual ~My_base(){} };
struct My_type: My_base {};
enum My_enum {};
auto main() -> int
{
My_base&& o = My_type();
cout << cppx::type_name<int>() << endl;
cout << cppx::type_name<My_enum>() << endl;
cout << cppx::type_name<My_type>() << endl;
cout << cppx::type_name( o ) << endl;
}
</file>