Print template typename at compile time

When creating a template function in C++ is there a simple way to have the typename of the template represented as a string? I have a simple test case to show what I'm trying to do (note the code shown does not compile):

#include <stdio.h>
template <typename type>
type print(type *addr) 
{
  printf("type is: %s",type);
}

int main()
{
  int a;
  print(&a);
}

// Would like to print something like:
// type is: int

I think that the typename should be available at compile time when the function is instantiated, but I'm not that familiar with templates and I haven't seen a way to get the typename as a string.

The reason that I want to do this is for some printf type debugging. I have multiple threads running and stepping through with gdb changes the program behavior. So for some things I want to dump information about which functions were executing. It's not too important so if the solution is overly complex I would skip adding this information to my logging function. But if there was a simple way to do this it would be useful information to have.

Answers


__PRETTY_FUNCTION__ should solve your problem (at run time at least)

The output to the program below is:

asfdasdfasdf test<type>::test() [with type = int]
asfdasdfasdf test<type>::test() [with type = int]
asfdasdfasdf test<type>::test() [with type = int]
asfdasdfasdf test<type>::test() [with type = int]
asfdasdfasdf test<type>::test() [with type = int]
asfdasdfasdf test<type>::test() [with type = int]
asfdasdfasdf void tempFunction() [with type = bool]
asfdasdfasdf void tempFunction() [with type = bool]
asfdasdfasdf void tempFunction() [with type = bool]
asfdasdfasdf void tempFunction() [with type = bool]
asfdasdfasdf void tempFunction() [with type = bool]
asfdasdfasdf void tempFunction() [with type = bool]
!!!Hello World!!!

If you really, really, need the typename as a string, you could hack this (using snprintf instead of printf) and pull the substring after '=' and before ']'.

#include <iostream>
using namespace std;

template<typename type>
class test
{
public:
test()
{
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__);
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__);
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__);
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__);
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__);
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__);
}
};

template<typename type>
void tempFunction()
{
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__);
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__);
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__);
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__);
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__);
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__);
}

int main() {
    test<int> test;

    tempFunction<bool>();
    cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
    return 0;
}

To get a useful compile time name:

Supposing you have some unknown type named 'T'. You can get the compiler to print it's type by using it horribly. For example:

typedef typename T::something_made_up X;

The error message will be like:

error: no type named 'something_made_up' in 'Wt::Dbo::ptr<trader::model::Candle>'

The bit after 'in' shows the type. (Only tested with clang).

Other ways of triggering it:

bool x = T::nothing;   // error: no member named 'nothing' in 'Wt::Dbo::ptr<trader::model::Candle>'
using X = typename T::nothing;  // error: no type named 'nothing' in 'Wt::Dbo::ptr<trader::model::Candle>'

With C++11, you may already have an object and use 'decltype' to get its type, so you can also run:

auto obj = creatSomeObject();
bool x = decltype(obj)::nothing; // (Where nothing is not a real member). 

Since you have said you would need this for debugging purpose, maybe a runtime solution is also acceptable. And you have tagged this as g++ so you don't want to be standard conform.

Here is what that means:

#include <cxxabi.h> // the libstdc++ used by g++ does contain this header

template <typename type>
void print(const type *addr) // you wanted a pointer
{
  char * name = abi::__cxa_demangle(typeid(*addr).name(), 0, 0, NULL);
  printf("type is: %s\n", name);
  delete name;
}

print(new unsigned long);    // prints "type is: unsigned long"
print(new std::vector<int>); // prints "type is: std::vector<int, std::allocator<int> >"

EDIT: corrected the memory leak. Thx to Jesse.


There is Boost.TypeIndex library.

See boost::typeindex::type_id for details.

It is very-easy-to-use, cross-platform and is real compile-type solution. Also it works as well even if no RTTI available. Also most of compilers are supported from the box.


Another compile time solution, similar to the one provided by matiu, but perhaps a little more descriptive would be to use a static_assert wrapped in a little helper function.

template<typename T>
void print_type_in_compilation_error(T&&)
{
    static_assert(std::is_same<T, int>::value && !std::is_same<T, int>::value, "Compilation failed because you wanted to read the type. See below");
}
// usage:
int I;
print_type_in_compilation_error(I);

The above will give you a nice error message (tested in MSVC and Clang) as in the other answer, but the code is IMHO better to understand.


if you have a known set of types used instantiate the template we can use the approach described in this older thread: stackoverflow.com/questions/1055452


Need Your Help

What happens to other threads when one thread forks()?

c++ multithreading pthreads fork

In C++ using pthreads, what happens to your other threads if one of your threads calls fork?

Accessing the ScrollViewer of a ListBox from C#

c# wpf xaml listbox scrollviewer

I'd like to change the properties of a ScrollViewer of a ListBox from C#.