How to find out the type of a variable?

I want to know the type of a variable (the variable is set by the Template parameter, so I don’t know what it is).

#include <iostream> #include <typeinfo> int main() { double test; std::cout << typeid(test).name() << std::endl; } 

But the code only emits: $. / Test

d

but instead I need a double.

The thing is, I don’t know what type to expect, but I have to write it in a routine that needs to be compiled. So d is a bad idea.

+6
source share
4 answers

GNU ABI has a helper for demonstrating name() typeid <Sub>

Disclaimer If this is not obvious, of course, GNU ABI only supports demarcing names from GNU ABI (and possibly not even wildly changing versions) .Sub>

 #include <cxxabi.h> #include <stdlib.h> #include <string> template <typename T> std::string nameofType(const T& v) { int status; char *realname = abi::__cxa_demangle(typeid(v).name(), 0, 0, &status); std::string name(realname? realname : "????"); free(realname); return name; } 
+2
source

If you know the list of types that you need to support, you can write your own function to do this:

 template <typename T> void printtype() { if (typeid(T) == typeid(double)) std::cout << "double"; else if (typeid(T) == typeid(int)) std::cout << "int"; } 

Note: since a function does not have an argument of type T, it should always have an explicit type:

 printtype<double>() 

and, of course, the type can be the type of the parameter:

 printtype<U>() 
+3
source

You can try to throw an error in the template with this expression as an argument, and the compiler error message will be of the type you are looking for.

For example, using GCC:

 #include <map> #include <string> template<typename T> void ErrorType(T &t) { char x[sizeof(t)==0 ? 1 : -1]; } template<typename T> void ErrorType(const T &t) { char x[sizeof(t)==0 ? 1 : -1]; } int main() { double d = 3; const double cd = 3; ErrorType(d); ErrorType(cd); ErrorType(3); std::map<std::string, int> x; ErrorType(x.begin()); } $ g++ -c test.cpp test.cpp: In function 'void ErrorType(T&) [with T = double]': test.cpp:17:20: instantiated from here test.cpp:6:14: error: size of array is negative test.cpp: In function 'void ErrorType(const T&) [with T = double]': test.cpp:18:21: instantiated from here test.cpp:10:14: error: size of array is negative test.cpp: In function 'void ErrorType(const T&) [with T = int]': test.cpp:19:20: instantiated from here test.cpp:10:14: error: size of array is negative test.cpp: In function 'void ErrorType(const T&) [with T = std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, int> >]': test.cpp:22:28: instantiated from here test.cpp:10:14: error: size of array is negative 

Thus, the types are reset double , int and std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, int> > . The first overload is not constant, which means that the expression is a non-constant l-value.

The trick sizeof(t)==0 necessary so that the whole expression depends on the template parameter and delays the error until an instance is created. The error itself (the size of the array is negative), of course, is meaningless.

And if you use C ++ 11, you can improve:

 #include <map> #include <string> template<typename T> void ErrorType(T &&t) { static_assert(sizeof(t)==0, "Reporting type name"); } int main() { double d = 3; const double cd = 3; ErrorType(d); ErrorType(cd); ErrorType(3); std::map<std::string, int> x; ErrorType(x.begin()); } $ g++ -c test.cpp -std=gnu++0x test.cpp: In function 'void ErrorType(T&&) [with T = double&]': test.cpp:15:20: instantiated from here test.cpp:6:9: error: static assertion failed: "Reporting type name" test.cpp: In function 'void ErrorType(T&&) [with T = const double&]': test.cpp:16:21: instantiated from here test.cpp:6:9: error: static assertion failed: "Reporting type name" test.cpp: In function 'void ErrorType(T&&) [with T = int]': test.cpp:17:20: instantiated from here test.cpp:6:9: error: static assertion failed: "Reporting type name" test.cpp: In function 'void ErrorType(T&&) [with T = std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, int> >]': test.cpp:20:28: instantiated from here test.cpp:6:9: error: static assertion failed: "Reporting type name" 

As an added bonus, this can make the difference between constants l-values ​​and r-values. The first is the value of double l, the second is a const double l, and the other two are the values ​​of r.

+2
source

Note. The string returned by the type_info member name depends on the specific implementation of your compiler and library. This is not necessarily a simple string with its typical type name, as in the compiler used to create this output.

What our compiler returned in a call to type_info :: name in this For example, our compilers generated names that are easily understood by people, but this is not a requirement: the compiler can simply return any string.

Source: http://www.cplusplus.com/doc/tutorial/typecasting/

My GCC produces malformed names. For instance. d for double , i for int , c for char and St6vectorIiSaIiEE for std::vector<int>

From the GCC type:

 /** Returns an @e implementation-defined byte string; this is not * portable between compilers! */ const char* name() const { return __name[0] == '*' ? __name + 1 : __name; } 

- edit -

You cannot "repeat" to get a name for compilers. If you want to do exactly what you have to hard code, as John Gorden describes in his post.

+1
source

Source: https://habr.com/ru/post/902260/


All Articles