__PRETTY_FUNCTION__
, __FUNCTION__
, __func__
有什么区别,它们在哪里记录?我如何决定使用哪一个?
原文由 Matt Joiner 发布,翻译遵循 CC BY-SA 4.0 许可协议
__PRETTY_FUNCTION__
, __FUNCTION__
, __func__
有什么区别,它们在哪里记录?我如何决定使用哪一个?
原文由 Matt Joiner 发布,翻译遵循 CC BY-SA 4.0 许可协议
__PRETTY_FUNCTION__
处理 C++ 特性:类、命名空间、模板和重载
主文件
#include <iostream>
namespace N {
class C {
public:
template <class T>
static void f(int i) {
(void)i;
std::cout << "__func__ " << __func__ << std::endl
<< "__FUNCTION__ " << __FUNCTION__ << std::endl
<< "__PRETTY_FUNCTION__ " << __PRETTY_FUNCTION__ << std::endl;
}
template <class T>
static void f(double f) {
(void)f;
std::cout << "__PRETTY_FUNCTION__ " << __PRETTY_FUNCTION__ << std::endl;
}
};
}
int main() {
N::C::f<char>(1);
N::C::f<void>(1.0);
}
编译并运行:
g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out
输出:
__func__ f
__FUNCTION__ f
__PRETTY_FUNCTION__ static void N::C::f(int) [with T = char]
__PRETTY_FUNCTION__ static void N::C::f(double) [with T = void]
您可能还对带有函数名称的堆栈跟踪感兴趣: print call stack in C or C++
在 Ubuntu 19.04、GCC 8.3.0 中测试。
C++20 std::source_location::function_name
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1208r5.pdf 进入了 C++20,所以我们还有另一种方法。
文档说:
constexpr const char* function_name() const noexcept;
6 返回:如果此对象表示函数体中的一个位置,则返回一个与函数名称对应的实现定义的 NTBS。否则,返回一个空字符串。
其中 NTBS 表示“空终止字节字符串”。
该功能存在于 GCC 11.2 Ubuntu 21.10 上,带有 -std=c++20
。它不在带有 g++-9 -std=c++2a
的 GCC 9.1.0 上。
https://en.cppreference.com/w/cpp/utility/source_location 显示用法是:
主文件
#include <iostream>
#include <string_view>
#include <source_location>
void log(std::string_view message,
const std::source_location& location = std::source_location::current()
) {
std::cout << "info:"
<< location.file_name() << ":"
<< location.line() << ":"
<< location.function_name() << " "
<< message << '\n';
}
int main() {
log("Hello world!");
}
编译并运行:
g++ -std=c++20 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out
输出:
info:main.cpp:17:int main() Hello world!
所以请注意它如何返回调用者信息,因此非常适合在日志记录中使用,另请参阅: Is there a way to get function name inside a C++ function?
原文由 Ciro Santilli OurBigBook.com 发布,翻译遵循 CC BY-SA 4.0 许可协议
3 回答2k 阅读✓ 已解决
2 回答3.9k 阅读✓ 已解决
2 回答3.2k 阅读✓ 已解决
1 回答3.2k 阅读✓ 已解决
1 回答2.7k 阅读✓ 已解决
3 回答3.4k 阅读
1 回答1.6k 阅读✓ 已解决
__func__
是一个隐式声明的标识符,当它在函数内部使用时扩展为包含函数名称的字符数组变量。它在 C99 中被添加到 C 中。从 C99 §6.4.2.2⁄1 开始:请注意,它不是宏,在预处理过程中没有特殊含义。
__func__
在 C++11 中被添加到 C++,其中它被指定为包含“实现定义的字符串”(C++11 §8.4.1[dcl.fct.def.general]/8 ),它不如 C 中的规范有用。(将__func__
添加到 C++ 的原始提议是 N1642 )。__FUNCTION__
是一些 C 编译器支持的预标准扩展(包括 gcc 和 Visual C++);一般来说,你应该在支持的地方使用__func__
并且只使用__FUNCTION__
如果你使用的编译器不支持它(例如,Visual C++,它不支持 C99并且还不支持所有 C++0x,不提供__func__
)。__PRETTY_FUNCTION__
是一个 gcc 扩展,与__FUNCTION__
相同,除了对于 C++ 函数,它包含函数的“漂亮”名称,包括函数的签名。 Visual C++ 有一个类似(但不完全相同)的扩展名__FUNCSIG__
。对于非标准宏,您需要查阅编译器的文档。 Visual C++ 扩展包含在 C++ 编译器的 “预定义宏” 的 MSDN 文档中。 gcc 文档扩展在 gcc 文档页面 “函数名称作为字符串”中进行了描述。