Reputation: 21
I would like to know if it is possible to know and output a template class name at compile time. It would look like something like this:
template<typename T>
class SomeTemplateClass
{
SOME_WAY_TO_PRINT_CLASS_NAME(T)
};
Then, each time the template class is called, for example:
using C = SomeTemplateClass<std::string>;
or
SomeTemplateClass<std::string> instance;
The compiler would echo a message like:
note: Template argument of SomeTemplateClass is std::__cxx11::basic_string<char>
As far as I searched, I found one way, that crashes the compiler to give the type of the class:
template<typename T>
class SomeTemplateClass
{
public:
using print = typename T::expected_crash;
};
using C = SomeTemplateClass<std::string>;
int main()
{
C::print err;
return 0;
}
That gives:
error: no type named ‘expected_crash’ in ‘class std::__cxx11::basic_string<char>’
But it is more a hack than a clean solution, and I was wondering if there was an other solution to this problem.
Thanks!
Upvotes: 2
Views: 442
Reputation: 21
There is an other hacky way to output a template class name at compilation, but without crashing the compiler. It is possible to use a warning, here a unused variable warning.
#define PRINT(T) template<typename T> \
int print_##T() \
{ \
int type_of_##T = 0; \
return 0; \
};\
int res_##T = print_##T<T>();
With this (and the -Wunused-variable flag), you can write
PRINT(T)
to know the type of T. Moreover, it is possible to use this solution inside a class, by creating a method, like this:
template<typename T>
class SomeTemplateClass
{
public:
static int print()
{
int type_of_T = 0;
return 0;
};
};
Method that will be called outside:
int useless = SomeTemplateClass<T>::print();
So it is still a hack, but at least the compiler does not crash any more.
Upvotes: 0
Reputation: 23711
This template has a dependent static_assert
that will always fail. Compilers usually show the template parameters that caused such an instantiation to fail.
template<class T>
struct NameOf {
static_assert(sizeof(T) != sizeof(T), "");
};
<source>: In instantiation of 'struct NameOf<SomeClass>': // <---
<source>:18:15: required from 'void foo(const T&) [with T = SomeClass]' // <---
<source>:24:10: required from here
<source>:9:29: error: static assertion failed
9 | static_assert(sizeof(T) != sizeof(T), "");
| ~~~~~~~~~~^~~~~~~~~~~~
You can do the same to have your compiler tell you the compile-time value of an arbitrary integer:
template<int I>
struct CompileTimeValueOf {
static_assert(I != I, "");
};
CompileTimeValueOf<sizeof(double)> x;
Note that this will of course make compilation fail, so it's just for temporary inspection. For anything less destructive, you'll probably have to resort to compiler-specific extensions. See for example here.
Upvotes: 0