Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

String representation of a type

359 views
Skip to first unread message

Scott Meyers

unread,
Jan 28, 2011, 11:14:56 PM1/28/11
to
The draft C++0x standard tells me (in 7.1.6.2/4) the following:

const int&& foo();
int i;
decltype(foo()) x1 = i; // type is const int&&

Suppose I'd like to verify that decltype(foo()) really returns the type
const int&&. How can I do that? If I apply typeid and then print the
type's name,

std::string s = typeid(decltype(foo())).name();
std::cout << s << '\n';

VC10 prints "int" and gcc 4.5 prints "i". Both are standard-conforming,
because std::typeinfo::name can return whatever it wants, but neither
helps me confirm that decltype returns what the draft standard says it
should.

In their book, "C++ Template Metaprogramming," David Abrahams and
Aleksey Gurtovoy recommend the following approach, which they say will
cause a diagnostic to be issued showing the type:

template<typename T> struct incomplete;

incomplete<decltype(foo())> x;

This works as advertised, yielding

types.cpp(51) : error C2079: 'x' uses undefined class 'incomplete<T>'
with
[
T=const int &&
]

on VC10 and

types.cpp:51:33: error: aggregate 'incomplete<const int &&> x' has
incomplete type and cannot be defined

with gcc 4.5. But I'd really like to have a lexical representation of
the type in a std::string at runtime, so the compile-time-diagnostic
trick is not what I'm looking for.

Using type traits and/or overloading, I could write the code to generate
a string representation of a type, but dealing with all the
possibilities (e.g., function types, member pointer types, pointers to
pointers to pointers..., const and/or volatile qualifiers, etc.) would
be, er, time-consuming. I'm hoping that somebody has already consumed
that time and shared their work with the world. Is there some code
floating around somewhere that takes a type and returns a string
representation of that type, i.e., something that would let me write
something like

std::string s = Type<decltype(foo())>().name();
std::cout s; // prints something like "const int &&"

Thanks,

Scott

Johannes Schaub (litb)

unread,
Jan 28, 2011, 11:57:33 PM1/28/11
to

Scott Meyers

unread,
Jan 31, 2011, 4:53:37 PM1/31/11
to
On 1/28/2011 8:57 PM, Johannes Schaub (litb) wrote:
> Someone already did that. See
> https://github.com/Eelis/geordi/blob/master/prelude/type_strings.hpp . Help
> is at http://www.xs4all.nl/~weegen/eelis/geordi/

I downloaded the source code and tried to find a way to use this
facility as part of a native C++ application, but it doesn't seem to be
designed to be used this way: it appears to be designed only to work on
Unix-like systems under gcc. Has anybody already ported this to
Windows? (gcc is fine, but it'd be nice if it ran under both gcc and
VC.) Or is there some other facility that will do what I want under
Windows?

Thanks,

Scott


Marc

unread,
Jan 31, 2011, 5:22:21 PM1/31/11
to
Scott Meyers wrote:

> The draft C++0x standard tells me (in 7.1.6.2/4) the following:
>
> const int&& foo();
> int i;
> decltype(foo()) x1 = i; // type is const int&&
>
> Suppose I'd like to verify that decltype(foo()) really returns the type
> const int&&. How can I do that? If I apply typeid and then print the
> type's name,
>
> std::string s = typeid(decltype(foo())).name();
> std::cout << s << '\n';
>
> VC10 prints "int" and gcc 4.5 prints "i". Both are standard-conforming,
> because std::typeinfo::name can return whatever it wants, but neither
> helps me confirm that decltype returns what the draft standard says it
> should.

They seem to ignore cvref qualifiers on the main type, but:
template<class>struct Dummy{};
typeid(Dummy<decltype(...)>).name() contains the information, with a
little noise on the side. Same for typeid(void(decltype(...))).name()
I guess, or anything that moves the cvref inside the type.

> In their book, "C++ Template Metaprogramming," David Abrahams and
> Aleksey Gurtovoy recommend the following approach, which they say will
> cause a diagnostic to be issued showing the type:
>
> template<typename T> struct incomplete;
>
> incomplete<decltype(foo())> x;

Yes, and it gives you the demangling for free :-)

> Using type traits and/or overloading, I could write the code to generate
> a string representation of a type, but dealing with all the
> possibilities (e.g., function types, member pointer types, pointers to
> pointers to pointers..., const and/or volatile qualifiers, etc.) would
> be, er, time-consuming.

Sounds like a nice "exercice for the reader" ;-)

Marc

unread,
Jan 31, 2011, 6:35:52 PM1/31/11
to
Marc wrote:

>> Using type traits and/or overloading, I could write the code to generate
>> a string representation of a type, but dealing with all the
>> possibilities (e.g., function types, member pointer types, pointers to
>> pointers to pointers..., const and/or volatile qualifiers, etc.) would
>> be, er, time-consuming.
>
> Sounds like a nice "exercice for the reader" ;-)

Like:
http://geometrica.saclay.inria.fr/team/Marc.Glisse/tmp/printtype.cpp

Scott Meyers

unread,
Jan 31, 2011, 11:56:19 PM1/31/11
to
On 1/31/2011 3:35 PM, Marc wrote:
> Like:
> http://geometrica.saclay.inria.fr/team/Marc.Glisse/tmp/printtype.cpp

Very sweet! Did you just whip this up on the spur of the moment?

Scott


Marc

unread,
Feb 1, 2011, 7:07:54 AM2/1/11
to
Scott Meyers wrote:

Yes, looked like fun. I probably missed a few corner cases though, and
the code could do with some cleanup...

Scott Meyers

unread,
Feb 1, 2011, 6:20:58 PM2/1/11
to
On 2/1/2011 4:07 AM, Marc wrote:
> Yes, looked like fun. I probably missed a few corner cases though, and
> the code could do with some cleanup...

Still, very impressive. And thanks!

Scott


Miles Bader

unread,
Feb 2, 2011, 12:18:02 AM2/2/11
to
Marc <marc....@gmail.com> writes:
>>> Like:
>>> http://geometrica.saclay.inria.fr/team/Marc.Glisse/tmp/printtype.cpp
>>
>> Very sweet! Did you just whip this up on the spur of the moment?
>
> Yes, looked like fun. I probably missed a few corner cases though, and
> the code could do with some cleanup...

Of course it depends on the system's type_info::name method to return
the names of class types, which it doesn't in gcc; in gcc,
type_info::name returns the mangled type name, so your proggie yields:

5Perso
unsigned long* const* volatile*&()
void(*&)(int(*)(),5Perso&)
5Perso const&(...)
long double(int volatile*,...)
int(5Perso::**)(double)
short const volatile 5Perso::*
int(*(*(&)(long))(char))(double)

I guess that could be worked-around by just skipping any digits at the
beginning of the class name, which obviously aren't a valid part of the
name...

-Miles

--
/\ /\
(^.^)
(")")
*This is the cute kitty virus, please copy this into your sig so it can spread.

Marc

unread,
Feb 2, 2011, 3:07:27 AM2/2/11
to
Miles Bader wrote:

> Marc <marc....@gmail.com> writes:
>>>> http://geometrica.saclay.inria.fr/team/Marc.Glisse/tmp/printtype.cpp


>
> Of course it depends on the system's type_info::name method to return
> the names of class types, which it doesn't in gcc; in gcc,
> type_info::name returns the mangled type name, so your proggie yields:

Well yes, I don't think there is much that can be done about it, so I
used type_info::name as a default. Note that you could still register
your own classes, templates, etc, but that's a not as nice.

> I guess that could be worked-around by just skipping any digits at the
> beginning of the class name, which obviously aren't a valid part of the
> name...

That might work for simple classes, but as soon as you add templates
to the mix... And you can't just stick _Z in front and call c++filt to
demangle, because sometimes you need a couple more letters in between.

Marc

unread,
Feb 2, 2011, 3:12:45 AM2/2/11
to
Marc wrote:

Indeed I had missed arrays. I added T[d] (works like functions, except
that removing extra parentheses is not so nice) but am still missing
T[]. I'll try to add it sometime.

Noah Roberts

unread,
Feb 2, 2011, 2:22:43 PM2/2/11
to
In article <ii0482$fqa$1...@news.albasani.net>, Neve...@aristeia.com
says...

> Using type traits and/or overloading, I could write the code to generate
> a string representation of a type, but dealing with all the
> possibilities (e.g., function types, member pointer types, pointers to
> pointers to pointers..., const and/or volatile qualifiers, etc.) would
> be, er, time-consuming. I'm hoping that somebody has already consumed
> that time and shared their work with the world. Is there some code
> floating around somewhere that takes a type and returns a string
> representation of that type, i.e., something that would let me write
> something like
>
> std::string s = Type<decltype(foo())>().name();
> std::cout s; // prints something like "const int &&"
>
> Thanks,
>
> Scott

The C++ TMP book reserves implementing something like this as an
exercize. You can see various solutions at the Wiki reserved for people
to share such answers:

http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?
CPPTM_Answers_-_Exercise_2-3


--
http://crazycpp.wordpress.com/

Marc

unread,
Feb 3, 2011, 5:01:19 AM2/3/11
to
Scott Meyers wrote:

> The draft C++0x standard tells me (in 7.1.6.2/4) the following:
>
> const int&& foo();
> int i;
> decltype(foo()) x1 = i; // type is const int&&
>
> Suppose I'd like to verify that decltype(foo()) really returns the type
> const int&&. How can I do that? If I apply typeid and then print the
> type's name,
>
> std::string s = typeid(decltype(foo())).name();
> std::cout << s << '\n';
>
> VC10 prints "int" and gcc 4.5 prints "i". Both are standard-conforming,
> because std::typeinfo::name can return whatever it wants, but neither
> helps me confirm that decltype returns what the draft standard says it
> should.

I just saw on the gcc mailing-list that typeid is actually forced to
ignore the cv-qualifiers:

"If the type of the type-id is a reference to a possibly cv-qualified
type, the result of the typeid expression refers to a std::type_info
object representing the cv-unqualified referenced type."

0 new messages