Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert typename T to string in c++ [duplicate]

Tags:

c++

templates

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.

like image 590
Srikanth Avatar asked Dec 19 '10 20:12

Srikanth


People also ask

What is typename in C?

" 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.

What is the difference between typename and class?

There is no difference between using <typename T> OR <class T> ; i.e. it is a convention used by C++ programmers.

Why is typename needed?

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).


5 Answers

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(); 
like image 163
atzz Avatar answered Sep 28 '22 17:09

atzz


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> 
like image 32
Industrial-antidepressant Avatar answered Sep 28 '22 17:09

Industrial-antidepressant


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.

like image 27
James McNellis Avatar answered Sep 28 '22 17:09

James McNellis


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...

like image 37
Mihran Hovsepyan Avatar answered Sep 28 '22 17:09

Mihran Hovsepyan


workaround way...

#define Tprint(x) print<x>(#x)

template<typename T>
void print (string ltype){
cout<<ltype<<" = "<<sizeof(T)<<endl;
}
like image 35
user3071398 Avatar answered Sep 28 '22 17:09

user3071398