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
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
> 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" ;-)
>> 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
Very sweet! Did you just whip this up on the spur of the moment?
Scott
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
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 <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.
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.
> 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
> 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."