4

I am looking for a way to obtain the name of a type, similar to typeid but for references. According to this page, typeid removes the reference.

If type is a reference type, the result refers to the referenced type.

I am looking for code similar to

int x = 5;
int & y = x;
wcout << typeid( y ).name();

but whose output is "int &" rather than "int".

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
Hector
  • 2,464
  • 3
  • 19
  • 34
  • Unrelated to your problem, but remember that the string returned by [`type_info::name`](http://en.cppreference.com/w/cpp/types/type_info/name) is *implementation specific*. If you change compiler the output might not be `int` at all. – Some programmer dude Feb 20 '15 at 04:58
  • How would you use it? – n. m. could be an AI Feb 20 '15 at 04:58
  • As for your problem, that's how references work, they reference something else so every time you use a reference it's the same as using what it references. – Some programmer dude Feb 20 '15 at 04:59
  • @n.m.: In a cycle where a C++ program inspects a C++ program and writes another C++ program. So, implementation dependent is OK as long as it has the references. – Hector Feb 20 '15 at 05:59

3 Answers3

7

The only portable way of doing this that I know of is to use Boost.TypeIndex

std::cout << boost::typeindex::type_id_with_cvr<decltype(x)>().pretty_name() << '\n';
std::cout << boost::typeindex::type_id_with_cvr<decltype(y)>().pretty_name() << '\n';

Prints

int
int&

Live demo

Praetorian
  • 106,671
  • 19
  • 240
  • 328
  • Boost.TypeIndex did not give me exactly what I needed. The references came out adorned with "_ptr64". – Hector Feb 20 '15 at 06:53
  • @Hector You got that from the `y` shown in the question? The only time I remember seeing `__ptr64` was when I was trying to figure out the return types of some member functions of the `vector` specialization on MSVC. Turns out those are [native pointer types](https://msdn.microsoft.com/en-us/library/aa985900.aspx) used by that compiler, so it really is part of the type name. I'm curious to see how you came across these, can you create a test case? – Praetorian Feb 20 '15 at 07:09
  • `boost::typeindex::type_id_with_cvr< struct A & >().pretty_name()` produces `struct A & __ptr64` in Visual Studio 2013 update 4. – Hector Feb 20 '15 at 09:11
  • @Hector Thank you. Unfortunately it doesn't look like you can avoid that because as the link above explains, that is the type used by the compiler. The `__ptr64` does disappear if you target x86 instead of x64. Another quirk I discovered is that MSVC's type name includes the calling convention. The second print statement of [this example](http://coliru.stacked-crooked.com/a/3100d67cb35a6f49) produces `void (__cdecl A::*)(void) __ptr64`. – Praetorian Feb 20 '15 at 15:18
7

See this answer for the C++11 way to do it - it involves using type_traits. Here is the relevant section of code:

#include <type_traits>
#include <typeinfo>
#ifndef _MSC_VER
#   include <cxxabi.h>
#endif
#include <memory>
#include <string>
#include <cstdlib>

template <class T>
std::string
type_name()
{
    typedef typename std::remove_reference<T>::type TR;
    std::unique_ptr<char, void(*)(void*)> own
           (
#ifndef _MSC_VER
                abi::__cxa_demangle(typeid(TR).name(), nullptr,
                                           nullptr, nullptr),
#else
                nullptr,
#endif
                std::free
           );
    std::string r = own != nullptr ? own.get() : typeid(TR).name();
    if (std::is_const<TR>::value)
        r += " const";
    if (std::is_volatile<TR>::value)
        r += " volatile";
    if (std::is_lvalue_reference<T>::value)
        r += "&";
    else if (std::is_rvalue_reference<T>::value)
        r += "&&";
    return r;
}
Community
  • 1
  • 1
SKK
  • 174
  • 1
  • 8
1

I found the following work-around to be very useful. I let the compiler fail with an error message telling me the actual type. To use the original poster's use case:

#include <type_traits>

int x = 5;
int & y = x;

static_assert(std::is_same<decltype(y), bool>::value, "");

clang, starting from version 8.0.0, outputs the following:

error: static_assert failed due to requirement 'std::is_same<int &, bool>::value'

You may find a working example in the Compiler Explorer.

  • Note 1: Obviously, if the type happens to be bool, the static assertion won't fail.
  • Note 2: I understand that this solution doesn't print the type, but it might be sufficient in some cases as it was for me.
Roland Sarrazin
  • 1,203
  • 11
  • 29