How to convert typename T to string in c++
You can't, at least not directly. The only way to convert a token or series of tokens into a string literal is using the preprocessor's stringization operator (#
) inside of a macro.
If you want to get a string literal representing the type, you'll have to write something yourself, perhaps by using a macro to instantiate the template and pass it the stringized type name.
One problem with any general approach is: what string should be given for the following uses:
Matrix<char> x;
typedef char MyChar;
Matrix<MyChar> y;
Both x
and y
are of the same type, but one uses char
directly and the other uses the typedef MyChar
.
It is impossilbe to get name of type in string
if the type is one of base types. For user defined types you can use typeid(my_type).name()
. Also you need #include <typeinfo>
:)
more info...
For GCC you have to use a trick. Using cxxabi.h
, I wrote a little wrapper for this purpose:
#include <string>
#include <iostream>
#include <iomanip>
#include <typeinfo>
#include <cxxabi.h>
#define DEBUG_TYPE(x) do { typedef void(*T)x; debug_type<T>(T(), #x); } while(0)
template<typename T>
struct debug_type
{
template<typename U>
debug_type(void(*)(U), const std::string& p_str)
{
std::string str(p_str.begin() + 1, p_str.end() - 1);
std::cout << str << " => ";
char * name = 0;
int status;
name = abi::__cxa_demangle(typeid(U).name(), 0, 0, &status);
if (name != 0) { std::cout << name << std::endl; }
else { std::cout << typeid(U).name() << std::endl; }
free(name);
}
};
The double parentheses are necessary. Will work with any type.
Now you can use it for boost::mpl
:
DEBUG_TYPE((if_c<true, true_, false_>::type));
will print:
if_c<true, true_, false_>::type => bool_<true>
There is no built-in mechanism for this.
typeid(T)::name()
can give some info, but the standard does not mandate this string to be human-readable; just that it has to be distinct for each type. (E.x. Microsoft Visual C++ uses human-readable strings; GCC does not.)
You can build your own system though. For example, traits-based. Something like this:
// default implementation
template <typename T>
struct TypeName
{
static const char* Get()
{
return typeid(T).name();
}
};
// a specialization for each type of those you want to support
// and don't like the string returned by typeid
template <>
struct TypeName<int>
{
static const char* Get()
{
return "int";
}
};
// usage:
const char* name = TypeName<MyType>::Get();