假设我有一个C ++模板函数。
template <class T>
int foo(T& t) {
...
}
如何以编程方式(而不是使用nm)计算函数的错位名称?
注意,我对demangling不感兴趣。我已经熟悉了进行demangling的cxxabi头文件。
答案 0 :(得分:1)
可以使用typeid
执行此操作;诀窍是通过创建一个带有非类型模板参数的类型将函数指针编码为类型名称,该参数的值是函数指针。例如:
template <class T> int foo(T&);
template <class U, U> struct IntegralConstant {};
std::cout << typeid(IntegralConstant<decltype(&foo<int>), &foo<int>>).name() << '\n';
这会输出16IntegralConstantIPFiRiEXadL_Z3fooIiEiRT_EEE
,通过c++filt -t
传送时会IntegralConstant<int (*)(int&), &(int foo<int>(int&))>
。棘手的一点是将符号_Z3fooIiEiRT_
(解码为int foo<int>(int&)
)与完整类型名称隔离开来;这可以通过在传递nullptr
代替函数指针时将受损的类型名称与等效项进行比较来完成:
template <class U, U> struct IntegralConstant {};
template <class U, U* u> std::string mangledSymbolName() {
std::string null = typeid(IntegralConstant<U*, nullptr>).name();
std::string symbol = typeid(IntegralConstant<U*, u>).name();
return symbol.substr(null.size() - 3, symbol.size() - null.size() + 0);
}
示例:http://melpon.org/wandbox/permlink/6b46CBOv0ZwIMukk
魔术常量3
和0
依赖于nullptr
的C ++ ABI中的编码,指向外部符号的指针和类模板;如果IntegralConstant
放在命名空间中,它们也需要调整。
答案 1 :(得分:-1)
您可以尝试获取callstack并从中获取函数名称,如下所示:
#include <iostream>
#include <string>
#include <regex>
#include <execinfo.h>
std::string GetMangledSymbol(const std::string& str)
{
static const std::regex regex(R"((\([a-zA-Z0-9_+]*\)))");
std::smatch matches;
std::regex_search( str, matches, regex );
if( ! matches.empty() )
{
auto symbolName = matches[1].str().substr(1);
auto pos = symbolName.find_first_of('+');
if( pos == std::string::npos)
return symbolName;
symbolName.erase( pos );
return symbolName;
}
return {};
}
void printCurrentFunction()
{
void* array[50] = { nullptr };
char** strings = nullptr;
size_t size = backtrace(array, 50);
strings = backtrace_symbols(array, size);
std::cout << GetMangledSymbol(strings[1]) << std::endl;
free(strings);
}
template <class T>
int foo(T&) {
printCurrentFunction();
return 0;
}
int main()
{
int i = 2;
foo(i);
std::string k;
foo(k);
}
使用gcc在linux上测试(需要-rdynamic标志)。