如何在C++(gcc)中获取完全限定的函数名,_excluding_返回类型?

mic*_*c_e 9 c++ gcc

此问题描述了如何使用__PRETTY_FUNCTION__获取函数的全名,包括其返回类型,参数类型,命名空间和模板参数.

考虑以下,美丽的功能:

namespace foo {
namespace {

template<int i>
int (*bar(int (*arg)(int *)))(int *) {
    printf("%s\n", __PRETTY_FUNCTION__);

    return arg;
}

} // anonymous namespace
} // namespace foo
Run Code Online (Sandbox Code Playgroud)

如果你不明白,该函数接受并返回一个指向int *- > int函数的指针.

g++(4.9)编译时,它的名字很漂亮,

int (* foo::{anonymous}::bar(int (*)(int*)))(int*) [with int i = 1337]
Run Code Online (Sandbox Code Playgroud)

并且,clang++(3.5),

int (*foo::(anonymous namespace)::bar(int (*)(int *)) [i = 1337])(int *)
Run Code Online (Sandbox Code Playgroud)

这些字符串非常不适合测试函数是否是某个命名空间的一部分.有没有其他方法,或者说,编译器提供的库来解析这些字符串?

为了澄清,我宁愿有类似的东西

foo::{anonymous}::bar <I don't care about anything beyond this point>
Run Code Online (Sandbox Code Playgroud)

更理想的是,我想要一种编译时的方式,比如一个产生某种列表的constexpr函数split(__PRETTY_FUNCTION__)

  • 完全限定的功能名称
  • 返回类型
  • arg0的类型
  • arg1的类型

等等,但我对完全合格的函数名称感到满意.

Col*_*mbo 5

经过更仔细的观察,我写了这段代码:

template <typename InputIterator, typename T>
InputIterator findClosing( InputIterator first, InputIterator last, T close )
{
    if (first == last)
        return last;

    auto open = *first;
    unsigned counter = 1;
    while (++first != last)
    {
        if (*first == close && --counter == 0)
            return first;
        if (*first == open)
            ++counter;
    }

    return last;
}

template <std::size_t N,
          std::size_t N2>
std::string f(char const(&str)[N], char const(&name)[N2])
{
    using namespace std;

    // Argument to isalnum must be unsigned:
    auto cond = [] (unsigned char c) {return !isalnum(c) && c != '_';};

    auto iter = str;
    for (;;++iter)
    {
        iter = search( iter, end(str),
                       begin(name), end(name)-1 );

        if (iter == end(str))
            throw invalid_argument("");

        if ((iter == begin(str)      || cond(iter[-1]))
         && (iter ==   end(str) - N2 || (cond(iter[N2-1]) && iter[N2-1] != ':')))
            break;
    }

    auto origin_iter = iter;
    while(iter != begin(str))
    {
        --iter;
        for (auto p : {"()", "{}"})
        if (*iter == p[1])
            iter = findClosing(reverse_iterator<char const*>(iter+1),
                               reverse_iterator<char const*>(begin(str)),
                               p[0]).base()-2;

        if (cond(*iter) && *iter != ':')
            return string(iter+1, origin_iter+N2-1);
    }

    return string(iter, origin_iter+N2-1);
}
Run Code Online (Sandbox Code Playgroud)

它应该适用于任何函数,假设其中不存在不必要的空格__PRETTY_FUNCTION__并且__func__仅包含非限定函数名称。

演示