假设您的C ++编译器支持它们,是否有任何特定的原因不使用__FILE__
,__LINE__
以及__FUNCTION__
出于日志记录和调试的目的?
我主要关心的是为用户提供误导性数据,例如,由于优化而报告错误的行号或功能,或者因此而导致性能下降。
基本上,我可以信任__FILE__
,__LINE__
并__FUNCTION__
以永远做正确的事?
假设您的C ++编译器支持它们,是否有任何特定的原因不使用__FILE__
,__LINE__
以及__FUNCTION__
出于日志记录和调试的目的?
我主要关心的是为用户提供误导性数据,例如,由于优化而报告错误的行号或功能,或者因此而导致性能下降。
基本上,我可以信任__FILE__
,__LINE__
并__FUNCTION__
以永远做正确的事?
Answers:
__FUNCTION__
是非标准的,__func__
存在于C99 / C ++ 11中。其他(__LINE__
和__FILE__
)都很好。
它将始终报告正确的文件和行(如果选择使用__FUNCTION__
/ ,则会报告功能__func__
)。优化不是一个因素,因为它是编译时宏扩展。它绝不会以任何方式影响性能。
__func__
在C ++中有点问题。C99没有说出默认参数之类的话,在不太明显的情况下,__func__
C ++应该如何表现。
__func__
存在于c99中,而不是c ++中。无论如何,我认为使用__func__
c ++ 进行合理的实现只会导致名称混乱。由于我不是编译器作家,所以这并不是我的真正要求。
__FUNCTION__
?除了最近的gcc之外,还有哪些编译器将其视为变量而不是宏?
__func__
现在是C ++ 11标准。
在极少数情况下,将给定的行更改为其他内容可能很有用__LINE__
。我已经看到GNU configure会在一些原始行文件中未出现的行之间插入一些伏都教之后,对某些测试报告适当的行号。例如:
#line 100
将使以下几行以__LINE__
100 开头。您可以选择添加新的文件名
#line 100 "file.c"
它很少有用。但是,如果有需要,我没有其他选择。实际上,代替行也可以使用宏,它必须导致上述两种形式中的任何一种。使用boost预处理程序库,您可以将当前行增加50:
#line BOOST_PP_ADD(__LINE__, 50)
我认为提及它很有用,因为您询问了__LINE__
and 的用法__FILE__
。人们永远不会从C ++中获得足够的惊喜:)
编辑: @Jonathan Leffler在评论中提供了一些更好的用例:
对于希望将用户C代码中报告的错误与用户源文件保持一致的预处理器,使用#line处理非常有用。Yacc,Lex和ESQL / C预处理器可以做到这一点。
仅供参考:g ++提供了非标准的__PRETTY_FUNCTION__宏。直到现在,我还不了解C99 __func __(感谢Evan!)。我认为当__PRETTY_FUNCTION__可以用于额外的班级范围定义时,我仍然更喜欢。
PS:
static string getScopedClassMethod( string thePrettyFunction )
{
size_t index = thePrettyFunction . find( "(" );
if ( index == string::npos )
return thePrettyFunction; /* Degenerate case */
thePrettyFunction . erase( index );
index = thePrettyFunction . rfind( " " );
if ( index == string::npos )
return thePrettyFunction; /* Degenerate case */
thePrettyFunction . erase( 0, index + 1 );
return thePrettyFunction; /* The scoped class name. */
}
C ++ 20 std::source_location
C ++最终添加了一个非宏选项,当C ++ 20广泛使用时,它将在将来的某个时候占主导地位:
该文档说:
constexpr const char * function_name()const noexcept;
6返回:如果此对象表示函数主体中的位置,则返回应与函数名称对应的实现定义的NTBS。否则,返回一个空字符串。
其中NTBS表示“空终止字节字符串”。
当GCC支持到达时,我会尝试一下,GCC 9.1.0 g++-9 -std=c++2a
仍然不支持它。
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!");
}
可能的输出:
info:main.cpp:16:main Hello world!
__PRETTY_FUNCTION__
vs __FUNCTION__
vs __func__
vsstd::source_location::function_name
<experimental/source_location>
目前GCC-9。