这就是我所做的:我有一个demangle()
函数(在其上实现abi::__cxa_demangle()
,我用几个方便的模板函数重载调用,nameof()
我想要字符串化的类型或相同的实例。
它相当紧凑,所以我将在这里重现它的所有荣耀。在demangle.hh
我们有:
#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 */
......然后在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 */
要使用它,我认为您必须链接到libc++
(或任何本地等效项)才能使用abi::__cxa_demangle()
. 对于 OP 来说可能不是最理想的是这样一个事实,即它在运行时进行了拆解和字符串化。我个人喜欢这种constexpr
对 leu 友好的东西,但由于我患有严重的宏观滥用过敏症,我发现这是解决这个问题的最不普遍不合理的解决方案。
(terminator
命名空间无关紧要——我在从终止处理程序调用的基于 libunwind 的堆栈跟踪器中使用此代码——随意使用s///g
该令牌)