如何在 c++ 中获取类名加函数名但没有能够处理模板函数、c 函数、静态函数等的参数?[复制]

How to get a class name plus function name but no args in c++ that is able to handle template function, c function, static function, etc? [duplicate]

提问人:Dachuan Huang 提问时间:11/15/2023 最后编辑:Scheff's CatDachuan Huang 更新时间:11/15/2023 访问量:121

问:

嗨,我知道这是一个古老的话题:如何获取 c++ 函数名称。但我真的没有看到一个令人满意的答案。

我正在使用 c++17,因此 c++20 功能不适用于我。

我需要一种可靠的方法,能够为类中的函数(静态和实例方法)打印“class_name::func_name()”,并为 c 样式函数打印“func_name()”。

该方法必须处理各种情况:

  1. 模板函数。
  2. 跳过所有参数。有时一个参数中包含“()”,例如,一个 std::function<void()> 类型的参数,因此很难解析。
  3. 静态函数和实例函数
  4. 嵌套类

我尝试了 、 、 并尝试用一些代码解析它们。我没有看到一种真正适用于所有情况的方法。__PRETTY_FUNCTION____FUNCTION____func__

谢谢。

++ 的 C++17

评论

4赞 Sam Varshavchik 11/15/2023
标准 C++ 库中根本没有任何东西可以做到这一点。
0赞 463035818_is_not_an_ai 11/15/2023
__func__是你能得到的最好的,但它仍然不是你想要的。
0赞 Pepijn Kramer 11/15/2023
@SamVarshavchik C++23 将有 en.cppreference.com/w/cpp/utility/basic_stacktraceC++ 每周在堆栈跟踪上
1赞 463035818_is_not_an_ai 11/15/2023
根据您对 std::source_location 的需要,它可能会有所帮助
0赞 463035818_is_not_an_ai 11/15/2023
顺便说一句,我不明白“所以很难解析”。你只需要寻找第一个和最后一个,不是吗?()

答:

3赞 Ted Lyngmo 11/15/2023 #1

您可以使用 std::source_location 来获取描述函数名称等的实现定义字符串。

例:

#include <iostream>
#include <source_location>

void log(std::ostream& os = std::cout,
         const std::source_location loc = std::source_location::current())
{
    os << loc.file_name() << '(' << loc.line() << "): "
       << loc.function_name() << '\n';
}

class Foo {
public:
    void func() const {
        log();
    }
};

int main() {
    log();
    
    Foo f;
    f.func();
}

可能的输出(在这种情况下,gcc 和 llvm 恰好一致):

/app/example.cpp(16): int main()
/app/example.cpp(11): void Foo::func() const

演示


在 C++17 中,如果使用标准库的 gcc 实现,则可以使用 :experimental/source_location

#include <experimental/source_location>
#include <iostream>

void log(std::ostream& os = std::cout,
         const std::experimental::source_location loc =
             std::experimental::source_location::current())
{
    os << loc.file_name() << '(' << loc.line() << "): "
       << loc.function_name() << '\n';
}

class Foo {
   public:
    void func() const { log(); }
};

int main() {
    log();

    Foo f;
    f.func();
}

评论

1赞 Dachuan Huang 11/15/2023
谢谢,但这是一个(自 C++20 以来)解决方案
1赞 Ted Lyngmo 11/15/2023
@DachuanHuang 抱歉,我错过了 C++17 位,但为此添加了可能的解决方法。
0赞 Dachuan Huang 11/19/2023
感谢您让我知道 cpp17 中的实验性源定位功能。不幸的是,它没有class_name字段。