Print a type's name at compile time without aborting compilation?

1k views Asked by At

In this question:

Print template typename at compile time

we have a few suggestions regarding how to get typical C++ compilers to print a type's name, at compile time. However, they rely on triggering a compilation error.

My question: Can I get the C++ compiler to print the name of a type without stopping compilation?

In general the answer is "probably not", because a valid program can be compiled into its target object without printing anything anywhere, so I'm asking specifically about GCC and clang, with possible use of preprocessor directives, compiler builtins, or any compiler-specific trick.

Notes:

  • Obviously, the challenge is printing types behind using/typedef statements, template parameter values, variadic templates etc. If the type is available explicitly you could just use something like #message "my type is unsigned long long" (as @NutCracker suggested). But that's not what the question is about.
  • Answers relying on C++11 or earlier are preferred to requiring C++14/17/20.
3

There are 3 answers

0
einpoklum On BEST ANSWER

The following mechanism is due to @JonathanWakely, and is specific to GCC:

int i;

template <typename T>
[[gnu::warning("type printed for your convenience")]]
bool your_type_was_() { return true; }

#define print_type_of(_x) your_type_was_<decltype(_x)>()

bool b = print_type_of(i);

This gives you:

<source>: In function 'void __static_initialization_and_destruction_0(int, int)':
<source>:7:55: warning: call to 'your_type_was_<int>' declared with attribute warning: type printed for your convenience [-Wattribute-warning]
    7 | #define print_type_of(_x) your_type_was_<decltype(_x)>()
      |                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
<source>:9:10: note: in expansion of macro 'print_type_of'
    9 | bool b = print_type_of(i);
      |          ^~~~~~~~~~~~~

See it working on Godbolt.

1
Klaus On

gcc and clang offers some interface for using own plugins which can do nearly everything on different stages from parsing to code generation.

The interfaces are compiler specific and as this a plugin for gcc can not be used for clang or visa versa.

The documentation is havy and there is no chance to go in any detail here, so I only point you to the docs from gcc and clang:

gcc plugin clang plugin

3
florestan On

In c++17 we can abuse the [[deprecated]] attribute to force the compiler to issue a warning containing the desired template parameter:

template<typename T>
[[deprecated]] inline constexpr void print_type(T&& t, const char* msg=nullptr){}

print_type(999, "I just want to know the type here...");

The snippet above will print the following warning with gcc:

<source>:32:59: warning: 'constexpr void print_type(T&&, const char*) [with T = int]' is deprecated [-Wdeprecated-declarations]
     print_type(999, "I just want to know the type here...");

In contrast to the accepted answer this will work with every c++17 compliant compiler. NB that you will have to enable \W3` on MSVC.

We can even go further and define a static assert macro that will print the type if and only if it fails.

template<bool b, typename T>
inline constexpr bool print_type_if_false(T&& t) {
    if constexpr (!b)
        print_type(std::forward<T>(t));
    return b;
}

// Some nice static assert that will print the type if it fails.
#define STATIC_ASSERT(x,condition, msg) static_assert(print_type_if_false<condition>(x), msg);

Here is a live example.