Is it possible in C++ to stringify template arguments? I tried this:
#define STRINGIFY(x) #x
template
struct Stringify
{
Stringify()
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
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();
template
char const* nameof() {
try {
return demangle(typeid(NameType).name());
} catch (std::bad_typeid const&) {
return "";
}
}
/// … or as implied by an instance argument:
/// char const* myinstancetypename = terminator::nameof(someinstance);
template
char const* nameof(ArgType argument) {
try {
return demangle(typeid(argument).name());
} catch (std::bad_typeid const&) {
return "";
}
}
} /* namespace terminator */
… And then in demangle.cpp:
#include "demangle.hh"
#include
#include
#include
#include
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 demangled_name{ nullptr, std::free };
#pragma clang diagnostic pop
}
char const* demangle(char const* const symbol) noexcept {
if (!symbol) { return ""; }
std::lock_guard 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)