Is it possible in C++ to stringify template arguments?
I tried this:
#include <iostream>
#define STRINGIFY(x) #x
template <typename T>
struct Stringify
{
Stringify()
{
std::cout << STRINGIFY(T) << endl;
}
};
int main()
{
Stringify<int> s;
}
But what I get is a T, and not an int. Seems that the preprocessor macros are evaluated before template instantiation.
Is there any other way to do this?
Is there any way for the preprocessing to take place after template instantiation? (Compiler is VC++).
You could try
typeid(T).name()
Edit: Fixed based on comments.
You could use some template magic.
#include <iostream>
template <typename T>
struct TypeName { static const char *name; };
template <typename T>
const char *TypeName<T>::name = "unknown";
template <>
const char *TypeName<int>::name = "int";
template <typename T>
struct Stringify
{
Stringify()
{
std::cout << TypeName<T>::name << std::endl;
}
};
int main()
{
Stringify<int> s;
}
This has an advantage over RTTI (i.e. typeinfo) - it is resolved during compilation; and disadvantage - you need to provide type information yourself (unless there is some library that does that already that I'm not aware of; maybe something in Boost even).
Or, as Martin York suggested in comments, use inline function templates instead:
template <typename T>
inline const char* typeName(void) { return "unknown"; }
template <>
inline const char* typeName<int>(void) { return "int"; }
// ...
std::cout << typeName<T>() << std::endl;
But, if you'll ever need to store more information about that particular type, then class templates will probably be better.
Your code doesn't work because the preprocessor, responsible for searching and expanding the macros you use in your code, is not aware of the language itself. It is just a text parser. It finds that STRINGIFY(T) in the very function template and expand it, much before you give a type to that template. As it turns out, you will always get "T" instead of the typename you expected, unfortunately.
As litb suggested, I've (badly) implemented this `getTypeName' function template that returns the typename you pass it:
#include <iostream>
template <typename _Get_TypeName>
const std::string &getTypeName()
{
static std::string name;
if (name.empty())
{
const char *beginStr = "_Get_TypeName =";
const size_t beginStrLen = 15; // Yes, I know...
// But isn't it better than strlen()?
size_t begin,length;
name = __PRETTY_FUNCTION__;
begin = name.find(beginStr) + beginStrLen + 1;
length = name.find("]",begin) - begin;
name = name.substr(begin,length);
}
return name;
}
int main()
{
typedef void (*T)(int,int);
// Using getTypeName()
std::cout << getTypeName<float>() << '\n';
std::cout << getTypeName<T>() << '\n'; // You don't actually need the
// typedef in this case, but
// for it to work with the
// typeid below, you'll need it
// Using typeid().name()
std::cout << typeid(float).name() << '\n';
std::cout << typeid(T).name() << '\n';
return 0;
}
The code above results in the following output with GCC flag -s ("strip all symbols from binary") enabled:
float
void (*)(int, int)
f
PFviiE
So, you see, getTypename() does a fairly better job, at the cost of that fugly string parsing hack (I KNOW, it's damn ugly).
A few points to take into account:
The code is GCC only. I don't know how to port it to another compiler. Probably only a few others have such a facility to produce so pretty function names, and from what I searched, MSVC++ doesn't have one, if you're asking yourself that.
If, in a new version, GCC formats __PRETTY_FUNCTION__'s differently, the string matching can break and you'll have to fix it. For this same reason I also warn that getTypeName() might be good for debugging (and, still, maybe not even good for that), but it is surely bad, bad, and bad for other purposes such as comparing two types in a template or something like that (I don't know, just guessing what someone might think of..). Use it solely for debugging, and preferentially don't call it in release builds (use macros to disable), so that you don't use __PRETTY_FUNCTION__ and thus the compiler doesn't produce the string for it.
I'm definitely no expert, and I'm not sure whether some odd type could cause the string matching to fail. I'd like to ask for people who read this post to comment if they know of such a case.
The code uses a static std::string. It means that, if some exception is thrown from its constructor or destructor, there is no way that it will reach a catch block and you'll get an unhandled exception. I don't know whether std::strings can do that, but beware that, if they do, you're potentially in trouble. I used it because it needs a destructor to free the memory. You could implement your own class for that, though, ensuring no exception is thrown besides allocation failure (that's pretty much fatal, isn't it? So...), and return a simple C-string.
With typedefs you can get some weird results, like this (for some reason, the site breaks the formatting of this snippet, so I'm using this paste link): http://pastebin.com/f51b888ad
Despite those disadvantages, I'd like to say that it sure is fast. For the second time you lookup for one same type name, it will cost picking a reference to a global std::string containing the name. And, comparatively to the template specialiazation methods suggested before, there is nothing else you have to declare besides the very template itself, so it is really much easier to use.
No, you cannot work on types as if they were variables. You could write code that extracted the typeid() of an element and printed the name, but the resulting value will probably not be what you expect (type names are not standarized).
You can also work with template specializations (and some macro magic) to achieve a more interesting version if the number of types you want to work with is limited:
template <typename T> const char* printtype(); // not implemented
// implement specializations for given types
#define DEFINE_PRINT_TYPE( type ) \
template<>\
const char* printtype<type>() {\
return #type;\
}
DEFINE_PRINT_TYPE( int );
DEFINE_PRINT_TYPE( double );
// ... and so on
#undef DEFINE_PRINT_TYPE
template <typename T> void test()
{
std::cout << printtype<T>() << std::endl;
}
int main() {
test<int>();
test<double>();
test<float>(); // compilation error, printtype undefined for float
}
Or you could even combine both versions: implement the printtype generic template using typeinfo and then provide specializations for the types you want to have fancier names.
template <typename T>
const char* printtype()
{
return typeid(T).name();
}
This breaks one of my primary tenets of C++ code writing: Avoid using tricks in both the template features and the preprocessor at the same time.
Part of the reason for templates and the nastiness they introduce into the language was an attempt to wean developers away from using the preprocessor. If you use both, then the terrorists win.
If you use boost/core/demangle.hpp, you can get a reliable human-readable string.
char const * name = typeid(T).name();
boost::core::scoped_demangled_name demangled( name );
std::cout << (demangled.get() ? demangled.get() : "Failed to demangle") << std::endl;
in my code I use the "awful" double-declaration of the "Class-Name"
MqFactoryC<MyServer>::Add("MyServer").Default();
because c++ is NOT able to extract the string "MyServer" from the template…
the only "way" to get "rid" of this… using a cpp "wrapper"
#define MQ_CPPSTR(s) #s
#define MqFactoryCAdd(T) MqFactoryC<T>::Add(MQ_CPPSTR(T)).Default()
Here’s what I do: I have a demangle() function (implemented on top of abi::__cxa_demangle() which I call with a couple of convenience template function overloads, nameof(), with either the type I want stringified or an instance of same.
It’s fairly compact, so I’ll reproduce it here in all its glory. In demangle.hh we have:
#pragma once
#include <typeinfo>
namespace terminator {
/// actual function to demangle an allegedly mangled thing
char const* demangle(char const* const symbol) noexcept;
/// convenience function template to stringify a name of a type,
/// either per an explicit specialization:
/// char const* mytypename = terminator::nameof<SomeType>();
template <typename NameType>
char const* nameof() {
try {
return demangle(typeid(NameType).name());
} catch (std::bad_typeid const&) {
return "<unknown>";
}
}
/// … or as implied by an instance argument:
/// char const* myinstancetypename = terminator::nameof(someinstance);
template <typename ArgType>
char const* nameof(ArgType argument) {
try {
return demangle(typeid(argument).name());
} catch (std::bad_typeid const&) {
return "<unknown>";
}
}
} /* namespace terminator */
… And then in demangle.cpp:
#include "demangle.hh"
#include <cstdlib>
#include <cxxabi.h>
#include <mutex>
#include <memory>
namespace terminator {
namespace {
/// define one singular, private, static std::mutex,
/// to keep the demangler from reentering itself
static std::mutex mangle_barrier;
/// define a corresponding private and static std::unique_ptr,
/// using a delete-expression to reclaim the memory malloc()'ed by
/// abi::__cxa_demangle() upon its return.
/// … we use clang pragmas to add flags locally for this to work:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wglobal-constructors"
#pragma clang diagnostic ignored "-Wexit-time-destructors"
std::unique_ptr<char, decltype(std::free)&> demangled_name{ nullptr, std::free };
#pragma clang diagnostic pop
}
char const* demangle(char const* const symbol) noexcept {
if (!symbol) { return "<null>"; }
std::lock_guard<std::mutex> lock(mangle_barrier);
int status = -4;
demangled_name.reset(
abi::__cxa_demangle(symbol,
demangled_name.get(),
nullptr, &status));
return ((status == 0) ? demangled_name.release() : symbol);
}
} /* namespace terminator */
To use this, I think you’ll have to link to libc++ (or whatever your local equivalent is) to use abi::__cxa_demangle(). What may be suboptimal for the OP is the fact that this does the demangling and stringification at runtime. I’d personally love something constexpr-friendly in leu of this, but since I suffer from a severe macro-abuse allergy, I find this to be the least generally-unreasonable solution to this problem.
(the terminator namespace is inconsequential – I use this code in a libunwind-based stacktracer called from termination handler – feel free to s///g that token)
Related
I try to expand my knowledge about macros and their usage.
I have a specific problem which i bumped.
Here's my situation
I have a class named RudyObject
This class has a get function for both member(GetRudyObjectID()) and static(GetStaticRudyObjectID()).
Here's my problem
I plan to create macro which adapts itself to given situation.
Here's the scenario i'd like to solve
TYPEOF(variable value type) should expand as variable.GetRudyObjectID()
TYPEOF(variable pointer) should expand as variable->GetRudyObjectID()
TYPEOF(type) should expand astype::GetStaticRudyObjectID()
Do you guys have any solution,tips or directios for this situation.
The first two you can easily get via a template with a specialization for pointers (via if constexpr) and the third is another overload only taking a template parameter:
#include <string>
#include <iostream>
template <typename T>
auto type_of(const T& t){
if constexpr (std::is_pointer_v<T>) {
return std::string{"a pointer \n"};
}
else {
return std::string{"not a pointer \n"};
}
}
template <typename T>
auto type_of() {
return std::string{"type_of without parameter \n"};
}
int main()
{
int x;
std::cout << type_of(x);
std::cout << type_of(&x);
std::cout << type_of<int>();
return 0;
}
Output:
not a pointer
a pointer
type_of without parameter
I advise you to not use macros for this. They have their place in automatic code generation, but using them to save a bit of typing will typically lead to hard to read, maintain and debug code when other C++ features can replace them easily without all those downsides. Moreover, macros are expanded before the code is compiled, ie the preprocessor does not know about types, pointers or variables. Macros are only about replacing tokens.
I am trying to write some templated functions that accept either a std::basic_string or a char array from which the basic_string could be constructed.
My current solution is:
#include <string>
template<typename CharT>
void foo(std::basic_string<CharT> str)
{
(void)str; // do something with str
}
template<typename CharT>
void foo(CharT const * arr)
{
return foo(std::basic_string<CharT>{arr});
}
int main(void)
{
foo("hello");
foo(std::string{ "hello" });
foo(L"hello");
foo(std::wstring{ L"hello" });
}
But this means that for each function I have to write another function that calls the first one. That's pretty annoying; is there an easier way to do it? Maybe it could be a template deduction guide, but as far as I know it does not exist for functions, only classes.
The first templated function is not sufficient because the template deduction fails: the compiler cannot deduce CharT in std::basic_string<CharT> from CharT const *. That is why I need a simpler way to tell this to the compiler.
Just bite the bullet and use 2 overloads. Any clever solution (which as davidhigh showed do exist) will only add unnecessary complexity, potential for bugs and confusion to the next reader.
You only write once but read multiple times. The small incovenient of writing a 1 line of body overload is worth doing against an non-idiomatic convoluted smart way.
Don't get me wrong, I love to find these smart solutions in C++, but if I found this solution in a production code it would take me a few good minutes just to figure out what the heck it is and what does it do, only to find out it just does what should have been a very basic thing in a complex way, I would ... well let's just say I wouldn't say nice things about the author of the code. Being lazy when writing code will cost you times over when you maintain, debug, extend, or even use the code.
Write simple, idiomatic and easy to understand code!
After a bit more of research, the best option imo is to use the C++17 feature std::basic_string_view:
template<typename CharT>
void foo(std::basic_string_view<CharT> str)
{
(void)str; // do something with str ...
// while remembering that string_view does not own the string
}
So forget about the older explanation below if you have access to a C++17-compiler.
There are two cases here to consider. The first case is that you do not really want to do something special with the basic string, but rather you apply only methods also available for the char-array (and just want to make sure it's called correctly regardless of the parameters). In this case, I'd simply use a general template parameter:
template<typename string_type
/* possibly some SFINAE to allow/disallow certain types */>
auto foo(string_type s)
{
std::cout << s << std::endl;
}
Second case is that you really want to do some special operation on the string which is not present for the char array. In this case you need an overload for basic_string, but you probably want to write it only once and not for each and every function you use. This is what the following string_invoker class tries to do (but it still needs some improvement, just working on it):
template<typename method>
struct string_invoker_impl
{
string_invoker_impl(method m) : m(m) {}
template<typename CharT>
auto operator()(std::basic_string<CharT> str) const
{
return m(str);
}
template<typename CharT>
auto operator()(CharT const * arr) const
{
return operator()(std::basic_string<CharT>{arr});
}
//possibly further methods for non-const array's, modification, etc.
method m;
};
auto string_invoker = [](auto m) { return string_invoker_impl<decltype(m)>{m}; };
auto foo_impl = [](auto str) {std::cout<< str <<std::endl; };
auto foo = string_invoker(foo_impl);
//you can merge the previous two calls also in a single one:
//auto foo = string_invoker( [](auto str) {std::cout<< str <<std::endl; });
int main(void)
{
foo("hello");
foo(std::string{ "hello" });
//foo(L"hello"); //need std::wcout, thus it fails with std::cout
//but it's no general problem, just overload your foo_impl function
//foo(std::wstring{ L"hello" });
}
DEMO
I would like to have a macro, say MAGIC, or MAGIC(*this) so that:
struct Foo {
Foo() {
cout << MAGIC; //Prints 1
}
void f() {
cout << MAGIC; //Prints 0
}
};
I'm only interested in this very usage. I don't care what happens when the macro is used from some other macro. It would be nice if it also worked for non-member functions.
The macro can theoretically also expand to some template trait that would then do the real magic.
I'm using MSVC, which provides a set of macros to get the current function name as a string literal. If I could compare that literal with the class name literal, which I also assume I can have, then I could do it (assuming there are no other issues linked to name mangling and templates), but you can't pass char* literals as template arguments, so I'm afraid it's impossible to achieve this.
I know it can be done at run time by using strcmp and maybe caching the result in a local static variable, but I'd like to have it at compile time.
EDIT
The following works on GCC, but it's really ugly, as it destroys the syntax.
It would be nice if I could at least use the opening curly braces as the traditional C++ syntax would require.
constexpr bool same_str(char const* a, char const* b) {
return *a==*b && (*a==0 || same_str(a+1, b+1));
}
template< bool bSame >
struct SSame {
static int const value = (int)bSame;
};
#define MAGIC SSame<same_str(c_strFuncName, c_strClassName)>::value
#define DEF_CLASS(x) x { constexpr static char const* c_strClassName = #x;
#define DEF_FUNC(x, ...) x(__VA_ARGS__) { constexpr static char const* c_strFuncName = #x;
struct DEF_CLASS(Foo)
DEF_FUNC(Foo)
cout << MAGIC;
}
void DEF_FUNC(f)
cout << MAGIC;
}
};
The simple answer is no. Macros are evaluated before the code
is parsed, so there is no way to obtain lexical context. As for
getting the current function name with a macro, that fails on
several counts: first, the macros which return the current function
name actually expand to the name of a compiler generated
variable which contains the name; second, there's no way
to compare strings in the macro anyway; and third, unless you
wanted to limit it to just one constructor, what name would you
compare it to anyway?
Is there a way to make static_assert's string being dynamically customized and then displayed?
What I mean is something like:
//pseudo code
static_assert(Check_Range<T>::value, "Value of " + typeof(T) + " type is not so good ;)");
No, there is not.
However this does not matter so much, because static_assert are evaluated at compile-time, and in case of error the compiler will not only print out the message itself, but it will also print the instanciation stack (in case of templates).
Have a look at this synthetic example in ideone:
#include <iostream>
template <typename T>
struct IsInteger { static bool const value = false; };
template <>
struct IsInteger<int> { static bool const value = true; };
template <typename T>
void DoSomething(T t) {
static_assert(IsInteger<T>::value, // 11
"not an integer");
std::cout << t;
}
int main() {
DoSomething("Hello, World!"); // 18
}
The compiler does not only emits the diagnostic, but it also emits the full stack:
prog.cpp: In function 'void DoSomething(T) [with T = const char*]':
prog.cpp:18:30: instantiated from here
prog.cpp:11:3: error: static assertion failed: "not an integer"
If you know Python or Java and how they print the stack in case of exception, it should be familiar. In fact, though, it's even better, because you not only get the call stack, but you also get the arguments values (types here)!
Therefore, dynamic messages are not as necessary :)
The standard specifies the second argument of static_assert to be a string literal, so no chance for computation there as far as I can see (except for preprocessor macros).
A compiler could extend the standard and allow const-expressions of approporiate type in this position, but I have no idea if any compiler does.
As Matthieu said, it's not possible, but you can get some of the functionalities you're looking for by using macros:
#define CHECK_TYPE_RANGE(type)\
static_assert(Check_Range<type>::value, "Value of " #type " type is not so good ;)");
CHECK_TYPE_RANGE(float); // outputs "Value of float type is not so good ;)"
This question already has answers here:
Can I obtain C++ type names in a constexpr way?
(3 answers)
Closed 1 year ago.
I want to get the type name and print it for debug purposes. I use the following code:
#include <cxxabi.h>
inline const char* demangle(const char *s) {
abi::__cxa_demangle(s, 0, 0, NULL);
}
template<typename T>
inline const char* type_name() {
return demangle(typeid(T).name());
}
It works well, but it I suppose there is an unnecessary runtime overhead. Is there any way to get a human-readable form of type ids that is computed at compile time? I am thinking of something that looks like this:
boost::mpl::type_name<MyType>::value
Which would return a string constant of the type name.
I can't see typeid(T).name() incurring a runtime overhead. typeid(expr) yes, if expr is of a polymorphic type.
It looks like the demangling probably happens at runtime, but there's not an awful lot you can do about that. If this is only for debugging then I really wouldn't worry about it too much unless your profiler indicates that this is causing your program to slow down so much that debugging other elements of it is troublesome.
I have the same need, I've solved it using the _____FUNCTION_____ maccro in a static method of my class. But you must do some runtine computation on _____FUNCTION_____ to extract the class name. You have to do some template tricks to avoid paste the same code in every class. If someone is interessed I may clean and translate my code from french to post it.
The main advantage of this method is that you don't need to enable RRTI. On the other hand, the extraction of the class name may be compiler dependant.
template <class MyT>
class NamedClass
{
static std::string ComputeClassName()
{
std::string funcMacro=__FUNCTION__;
//compiler dependant
static const std::string start="scul::NamedClass<class ";
static const std::string end=">::ComputeClassName";
return funcMacro.substr(start.size(),funcMacro.size()-end.size()-start.size());;
}
static const std::string _ClassName;
};
template <class MyT>
const std::string NamedClass<MyT>::_ClassName=NamedClass<MyT>::ComputeClassName();
In C++ 20
You can use the standard std::source_location where its static method ::current is consteval in which you can use it at compile-time and then you can obtain the function_name method.
template <typename T>
consteval auto func_name() {
const auto& loc = std::source_location::current();
return loc.function_name();
}
template <typename T>
consteval std::string_view type_of_impl_() {
constexpr std::string_view functionName = func_name<T>();
// since func_name_ is 'consteval auto func_name() [with T = ...]'
// we can simply get the subrange
// because the position after the equal will never change since
// the same function name is used
// another notice: these magic numbers will not work on MSVC
return {functionName.begin() + 37, functionName.end() - 1};
}
template <typename T>
constexpr auto type_of(T&& arg) {
return type_of_impl_<decltype(arg)>();
}
template <typename T>
constexpr auto type_of() {
return type_of_impl_<T>();
}
Note: The function name from the source location object may vary from compiler-to-compiler and you can use the macro __PRETTY_FUNCTION__ or any other related macros if your compiler doesn't yet support the source location library.
Usage:
int x = 4;
// type_of also preserves value category and const-qualifiers
// note: it returns std::string_view
type_of(3); // int&&
type_of(x); // int&
type_of(std::as_const(x)); // const int&
type_of(std::move(x)); // int&&
type_of(const_cast<const int&&>(x)); // const int&&
struct del { del() = delete; };
type_of<del>(); // main()::del (if inside main function)
// type_of(del{}); -- error
type_of<int>(); // int
type_of<const int&>(); // const int&
type_of<std::string_view>(); // std::basic_string_view<char>
type_of([]{}); // main()::<lambda()>&&
type_of<decltype([]{})>(); // main()::<lambda()>
type_of<std::make_index_sequence<3>>(); // std::integer_sequence<long unsigned int, 0, 1, 2>
// let's assume this class template is defined outside main function:
template <auto X> struct hello {};
type_of<hello<1>>(); // hello<1>
type_of<hello<3.14f>>(); // hello<3.1400001e+0f>
// also this:
struct point { int x, y; };
type_of<hello<point{.x = 1, .y = 2}>>() // hello<point{1, 2}>
Advantage of using this type_of over demangling in typeid(...).name():
(also noted: I didn't test other compiler's ability, so I only guarantee for GCC)
You can check the value at compile-time, such that static_assert(type_of(4.0) == "double&&") is valid.
There is no runtime overhead.
The operation can be done either at runtime or compile-time (depending on the argument given whether it's usable in a constant expression).
It preserves cv-ref traits (const, volatile, & and &&).
You can alternatively use the template argument just in case the type's constructor is deleted and test without the cv-ref traits.
You could use std::type_index to cache the demangled strings.
You could use an std::map or similar data structure (splay trees for example) to cache and access the demangled name relatively quickly. It's not done in compile time though, I doubt the latter is possible.