While playing with templates in c++ I encountered a problem converting typename T to string. For example:
template <typename T>
class Matrix {
public:
Matrix() {
//my_type = string type of T. i.e. if T is char. I want my_type to be "char".
}
string my_type;
}
How do I convert T to a string that says what T is.
Note: I'm just playing around so please do not worry about when one might need such a thing.
" typename " is a keyword in the C++ programming language used when writing templates. It is used for specifying that a dependent name in a template definition or declaration is a type.
There is no difference between using <typename T> OR <class T> ; i.e. it is a convention used by C++ programmers.
The typename keyword is needed whenever a type name depends on a template parameter, (so the compiler can 'know' the semantics of an identifier (type or value) without having a full symbol table at the first pass).
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();
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>
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...
workaround way...
#define Tprint(x) print<x>(#x)
template<typename T>
void print (string ltype){
cout<<ltype<<" = "<<sizeof(T)<<endl;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With