473,416 Members | 1,762 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,416 software developers and data experts.

typeid(T).nameOfTheBeast()

Sometimes, in an introspective mood, my code reflecting on itself, I like to
write test code that prints the results of introspection, some of which
consist of the names of Types. The problem is: typeid(T).name(), in my
usual worlds (e.g. gcc version 3.2.2 [FreeBSD] 20030205 (release)), returns
an illegible mangling or a cryptic abbreviation. For example:

typeid(unsigned int).name()

returns "j". And while I do appreciate the savings involved it nonetheless
irritates readers of the output - rather than "j" they would like to see
"unsigned int". Bother!

So I had a thought:

template<typename T>
struct TName
{
static const char* Is()
{
return typeid(T).name();
}
};

template<>
struct TName<bool>
{
static const char* Is() { return "bool"; }
};

....

template<>
struct TName<long double>
{
static const char* Is() { return "long double"; }
};

And those homegrown Types that want to play nice do this:

template<> struct TName<AClass>
{ static const char* Is() { return "AClass"; } };

Any better ideas?
Jul 23 '05 #1
17 3127
Michael Olea wrote:
Sometimes, in an introspective mood, my code reflecting on itself, I like to
write test code that prints the results of introspection, some of which
consist of the names of Types. The problem is: typeid(T).name(), in my
usual worlds (e.g. gcc version 3.2.2 [FreeBSD] 20030205 (release)), returns
an illegible mangling or a cryptic abbreviation. For example:

typeid(unsigned int).name()

Why not just use overloaded functions, e.g.

const char* is (bool b) { return "bool";}
const char* is (const long double& ld) { return "long double";}

template <typename T>
const char* is (const T& t) { return typeid(T).name();}
void foo() {
bool test;
cout << "current type is " << is(test) << endl;
cout << "current type is " << is(std::string()) << endl;
}

Jul 23 '05 #2
Michael Olea wrote:
Sometimes, in an introspective mood, my code reflecting on itself, I like
to write test code that prints the results of introspection, some of which
consist of the names of Types. The problem is: typeid(T).name(), in my
usual worlds (e.g. gcc version 3.2.2 [FreeBSD] 20030205 (release)),
returns an illegible mangling or a cryptic abbreviation. For example:

typeid(unsigned int).name()

returns "j". And while I do appreciate the savings involved it nonetheless
irritates readers of the output - rather than "j" they would like to see
"unsigned int". Bother!


Well, if you can live with using compiler specific functionality here, then
you could demangle that name. g++ uses just the same string that would be
used in name mangling. Look into the cxxabi.h header. It provides a
function abi::__cxa_demangle() that can convert the name returned by
typeid(T).name() into what you want.

xpost&f'up2 gnu.g++.help, because that group is clearly more appropriate for
answers to my posting.

Jul 23 '05 #3
Michael Olea wrote:
Sometimes, in an introspective mood, my code reflecting on itself, I like to
write test code that prints the results of introspection, some of which
consist of the names of Types. The problem is: typeid(T).name(), in my
usual worlds (e.g. gcc version 3.2.2 [FreeBSD] 20030205 (release)), returns
an illegible mangling or a cryptic abbreviation. For example:

typeid(unsigned int).name()

returns "j". And while I do appreciate the savings involved it nonetheless
irritates readers of the output - rather than "j" they would like to see
"unsigned int". Bother!


The GNU utility c++filt, which demangles symbol names, is a wrapper
around a library function from binutils (libbfd?) whose prototype I
can't immediately find in /usr/include. It takes mangled symbol names
like _Z23frobnicateRK213_fooBlah and turns them into `string
frobnicate(unsigned int, struct foo)'; I believe that it is doing what
you need to get the parameter types. However I don't recall it having a
public interface for just doing the type demangling.

grepping in /usr/include has revealed something called __cxa_demangle in
/usr/include/c++/3.3/cxxabi.h. Not sure how that is related.

If all else fails I'm sure the binutils source, grepped for mangl, will
reveal the answer.

--Phil.
Jul 23 '05 #4
ben
> Why not just use overloaded functions, e.g.

because you need an instance of the type to pass as parameter, consider:

class shape
{
public:
virtual draw() = 0;
};

const char* is (shape a); // illegal

ben

const char* is (bool b) { return "bool";}
const char* is (const long double& ld) { return "long double";}

template <typename T>
const char* is (const T& t) { return typeid(T).name();}
void foo() {
bool test;
cout << "current type is " << is(test) << endl;
cout << "current type is " << is(std::string()) << endl;
}

Jul 23 '05 #5
Phil Endecott wrote:
Michael Olea wrote:
Sometimes, in an introspective mood, my code reflecting on itself, I like
to write test code that prints the results of introspection, some of
which consist of the names of Types. The problem is: typeid(T).name(), in
my usual worlds (e.g. gcc version 3.2.2 [FreeBSD] 20030205 (release)),
returns an illegible mangling or a cryptic abbreviation. For example:

typeid(unsigned int).name()

returns "j". And while I do appreciate the savings involved it
nonetheless irritates readers of the output - rather than "j" they would
like to see "unsigned int". Bother!


The GNU utility c++filt, which demangles symbol names, is a wrapper
around a library function from binutils (libbfd?) whose prototype I
can't immediately find in /usr/include. It takes mangled symbol names
like _Z23frobnicateRK213_fooBlah and turns them into `string
frobnicate(unsigned int, struct foo)'; I believe that it is doing what
you need to get the parameter types. However I don't recall it having a
public interface for just doing the type demangling.

grepping in /usr/include has revealed something called __cxa_demangle in
/usr/include/c++/3.3/cxxabi.h. Not sure how that is related.

If all else fails I'm sure the binutils source, grepped for mangl, will
reveal the answer.

--Phil.


I find this to be a fairly telling observation regarding where introspection
can, in general, be useful. This is by no means an exclusive rule, but my
observation is that introspection is often most useful at
design/coding/debugging time, rather than production runtime. I would like
to see a generic interface that hides compiler specific idiosyncracies, and
provides the kind of introspection and reflection that's useful to the
programmer, and tool developer in the way Java's javap command is for that
language. I'd even begrudgingly entertain the notion that a bit of #MACRO
magic might be useful in this respect.
--
If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true.-Bertrand Russell
Jul 23 '05 #6
ben wrote:
Why not just use overloaded functions, e.g.
because you need an instance of the type to pass as parameter, consider:


which is a feature, not a liability. You don't need to type the actual
type.
class shape
{
public:
virtual draw() = 0;
};

const char* is (shape a); // illegal


What's your point? Do you want something like this?

#define IS(type) (#type)
cout << "current type is " << IS(shape) << endl;

Jul 23 '05 #7
ben
> I would like
to see a generic interface that hides compiler specific idiosyncracies, and provides the kind of introspection and reflection that's useful to the
programmer, and tool developer in the way Java's javap command is for that
language. I'd even begrudgingly entertain the notion that a bit of #MACRO
magic might be useful in this respect.


I really think and hope that the static type reflection mechanism, which
does exactly what the OP requested, is going to be part of the C++0x
standard. But since that will take AGES AND AGES (2009?) to happen and then
AGES AND AGES(2015?) for the compiler vendors to adopt, we will have to hand
write a lot of template specialization before that. And yes, #MACRO helps!

ben
Jul 23 '05 #8
ben
> which is a feature, not a liability. You don't need to type the actual
type.
class shape
{
public:
virtual draw() = 0;
};

const char* is (shape a); // illegal


What's your point? Do you want something like this?

#define IS(type) (#type)
cout << "current type is " << IS(shape) << endl;


What I want, what the OP probably wants, is a typeid() operator without any
name mangling. A workaround would be something like:

cout << type_name<shape>::is(); // prints "shape"

And a helper function can be easily provided to take objects instead of
types:

template <typename T>
char* type_name_of(const T& instance)
{
return type_name<T>::is();
}

shape* s = new circle;
cout << "current type is " << type_name_of(*s);
delete s;

ben
Jul 23 '05 #9
ben
> which is a feature, not a liability. You don't need to type the actual
type.
class shape
{
public:
virtual draw() = 0;
};

const char* is (shape a); // illegal
What's your point? Do you want something like this?

#define IS(type) (#type)
cout << "current type is " << IS(shape) << endl;


What I want, what the OP probably wants, is a typeid() operator without any
name mangling. A workaround would be something like:

cout << type_name<shape>::is(); // prints "shape"

And a helper function can be easily provided to take objects instead of
types:

template <typename T>
char* type_name_of(const T& instance)
{
return type_name<T>::is();
}

shape* s = new circle;
cout << "current type is " << type_name_of(*s);
delete s;

ben
"Panjandrum" <pa********@spambob.com> wrote in message
news:11*********************@f14g2000cwb.googlegro ups.com... ben wrote:
Why not just use overloaded functions, e.g.


because you need an instance of the type to pass as parameter, consider:


which is a feature, not a liability. You don't need to type the actual
type.
class shape
{
public:
virtual draw() = 0;
};

const char* is (shape a); // illegal


What's your point? Do you want something like this?

#define IS(type) (#type)
cout << "current type is " << IS(shape) << endl;

Jul 23 '05 #10

"Panjandrum" <pa********@spambob.com> wrote in message
news:11**********************@o13g2000cwo.googlegr oups.com...
Michael Olea wrote:
Sometimes, in an introspective mood, my code reflecting on itself, I like
to
write test code that prints the results of introspection, some of which
consist of the names of Types. The problem is: typeid(T).name(), in my
usual worlds (e.g. gcc version 3.2.2 [FreeBSD] 20030205 (release)),
returns
an illegible mangling or a cryptic abbreviation. For example:

typeid(unsigned int).name()

Why not just use overloaded functions, e.g.

const char* is (bool b) { return "bool";}
const char* is (const long double& ld) { return "long double";}

template <typename T>
const char* is (const T& t) { return typeid(T).name();}


For one thing, functions cannot be partially specialized.

template<typename T>
struct TName<std::vector<T> >
{
static const char* Is()
{
static std::string namestring =
"std::vector<" + std::string(TName<T>::Is()) + ">";
return namestring.c_str();
}
};
Jul 23 '05 #11
ben
> template <typename T>
char* type_name_of(const T& instance)
{
return type_name<T>::is();
}

shape* s = new circle;
cout << "current type is " << type_name_of(*s);
delete s;


Oops! Sorry! This still prints "shape" instead of "circle". Obviously, some
runtime operation has to perform to trace to the most derived type...which
is what typeid does. For objects instead of pointers the template works
fine:

circle c;
cout << "current type is " << type_name_of(c); // prints "circle"

ben
Jul 23 '05 #12
ben wrote:
[...] I'd even begrudgingly entertain the notion that a bit of
#MACRO magic might be useful in this respect.


I really think and hope that the static type reflection mechanism, which
does exactly what the OP requested, is going to be part of the C++0x
standard. But since that will take AGES AND AGES (2009?) to happen and
then AGES AND AGES(2015?) for the compiler vendors to adopt, we will have
to hand write a lot of template specialization before that. And yes,
#MACRO helps!

ben


What is #MACRO? Where can I read about it? Or is it just a generic notation
for preprocessor foo? (I did find the Monopole Astrophysics and Cosmic Ray
Observatory, but somehow I doubt that's what y'all are talking about.)
Jul 23 '05 #13
ben
> What is #MACRO? Where can I read about it? Or is it just a generic
notation
for preprocessor foo? (I did find the Monopole Astrophysics and Cosmic Ray
Observatory, but somehow I doubt that's what y'all are talking about.)


LOL! Yes, it is just a preprocessor foo.
ben
Jul 23 '05 #14

Panjandrum wrote:
Michael Olea wrote:
Sometimes, in an introspective mood, my code reflecting on itself, I like to
write test code that prints the results of introspection, some of which
consist of the names of Types. The problem is: typeid(T).name(), in my
usual worlds (e.g. gcc version 3.2.2 [FreeBSD] 20030205 (release)), returns
an illegible mangling or a cryptic abbreviation. For example:

typeid(unsigned int).name()

Why not just use overloaded functions, e.g.

const char* is (bool b) { return "bool";}
const char* is (const long double& ld) { return "long double";}

template <typename T>
const char* is (const T& t) { return typeid(T).name();}


The disadvantage of using overloaded functions to identify a type is
that the compiler is free to promote or convert the type passed in the
function call in order to match the signature of an overloaded
function, if necessary. For example, if is(int) were declared but not
is(bool), then is(int) would be called for any variable of type bool.
Examining the output of the program would not be enough to indicate
that bools are being reported as ints; it may just be that no bools are
being asked to report their type.

The advantage of the template approach is that there is no type
conversion applied for a parameterized type. TName<int> will never
match a TName<bool>. So if TName<bool> is not declared then the
non-specialized TName class template is applied; the output for a bool
type would be "B" (or whatever). It would not be an "int." Examining
this output, the presence of the "B" types makes clear that there is a
type that needs a specialized TName template.

Greg

Jul 23 '05 #15
Greg wrote:
The advantage of the template approach is that there is no type
conversion applied for a parameterized type. TName<int> will never
match a TName<bool>. So if TName<bool> is not declared then the
non-specialized TName class template is applied; the output for a bool
type would be "B" (or whatever). It would not be an "int." Examining
this output, the presence of the "B" types makes clear that there is a
type that needs a specialized TName template.


Question: Why would someone want to write
const char* s = TName<bool>::Is();

instead of
const char* s = "bool"

Jul 23 '05 #16
ben


Question: Why would someone want to write
const char* s = TName<bool>::Is();

instead of
const char* s = "bool"


If you have a lot of typedef's its sometimes good to figure out what the
underlying type is.
If you are writing templates and want to generate some debugging information
it is good to know the type name.

ben
Jul 23 '05 #17

Panjandrum wrote:
Greg wrote:
The advantage of the template approach is that there is no type
conversion applied for a parameterized type. TName<int> will never
match a TName<bool>. So if TName<bool> is not declared then the
non-specialized TName class template is applied; the output for a bool
type would be "B" (or whatever). It would not be an "int." Examining
this output, the presence of the "B" types makes clear that there is a
type that needs a specialized TName template.


Question: Why would someone want to write
const char* s = TName<bool>::Is();

instead of
const char* s = "bool"


If the goal were to declare a const char *s initialized with a pointer
to the string "bool" then the TName class template would not be all
that useful. But in those situations in which the type being reported
is not hard-coded, then the value of declaring a TName class becomes
more apparent.

For example, take a simple function template:

void MyFunction( T a )
{
std::cout << "MyFunction instatiated with type: " << TName<T>::Is()
<< " and value: " << a << std::endl;
....
}

If MyFunction accepted only a bool parameter than TName would not be
needed to report a's type. But since a's type is not hardcoded, and
could be any kind of type both now and in the future, then TName's
ability to select the correct name based on a's actual type is very
useful in reporting what MyFunction is doing.

Greg

Jul 23 '05 #18

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

18
by: Andreas Sch. | last post by:
Hello, I had been quite suprised by the following little program: ---- cut ---- #include "iostream.h" class base {
11
by: Jamie Burns | last post by:
Hello, I just did a simple benchmark: for (xx=0;xx<100000;xx++) { rDerived* derived = dynamic_cast<rDerived*>(object); if (derived) derived->setValue(message.data.messageSetInt.value); } ...
3
by: Mike | last post by:
I want to use typeid() in a base class function to determine the name of the derived class. typeid(this) returns the name of the base class (which is an abstract class) rather than the derived...
3
by: Max | last post by:
I am trying to find a way to eliminate vararg functions from my code by packaging the input parameters in stringstreams. Here is an oversimplified example of what I am trying to do: Functions...
19
by: Marco Jez | last post by:
Hi everyone! I would like to use the reference returned by typeid as key in a std::map. Is it safe to assume that typeid(T) (where T is a type name) will always return the same reference to the...
18
by: Adam Zimny | last post by:
This is fragment of code from Bruce Eckel's Thinking in c++ ( last 3 couts are mine to show what happened ). The question is: is Bruce Eckel wrong or g++ ( my version is 3.2.3 ) is buggy ? //:...
5
by: nobody | last post by:
With Visual C++ 2005 beta 2, I get the below compling error for the following code. I think this error is not acceptable to me because int::typeid is a constant and is known to compiler when...
6
by: ma740988 | last post by:
I was trying to garner a feel for typeid and it's use with polymorphic types #include <iostream> template <class T> bool is_polymorphic() { bool result(false); typeid( (result=true),...
7
by: Deepak Jharodia | last post by:
I'm using a templatized class in GCC based environ template<class A, class B> class foo {... ....} F; Now I want to know that particular instance of this class was instantiated with what...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.