C++20 的 std::source_location 比预定义的宏 __FILE__、__LINE__ 和 __FUNCTION__ 有什么优势?

Ros*_*n M 9 c++ c++20

在我当前的项目中,我使用了:

Log(__LINE__, __FUNCTION__, message);
Run Code Online (Sandbox Code Playgroud)

但是新的 C++20 实用程序类std::source_location 带有函数line(), column(), file_name(), function_name(),它们做同样的事情。因此,新的 C++20 方式将是:

log(std::string message,const std::source_location& location = std::source_location::current())
{
    std::cout << "Debug:"
              << location.file_name() << ':'
              << location.line() << ' '
              << message << '\n';
}
Run Code Online (Sandbox Code Playgroud)

什么是新的,C ++ 20比旧标准双下划线宏方式的优点__LINE____FILE____func__,这已经被标准C ++很长一段时间?

我正在尝试确定优势是否如此之大,以至于证明修改我当前项目中的代码std::source_location以优先使用新对象而不是宏是合理的。

for*_*818 23

你的例子是我能想到的最好的动力。在过去__LINE__, 和_FILE__是使用宏进行调试日志的最佳借口。现在这不再成立了。

过去你基本上有两种选择。要么让调用者传递有关日志记录发生位置的信息:

log(__LINE__,__FILE__,"Hello World");
Run Code Online (Sandbox Code Playgroud)

或使用宏通过以下方式获得相同的输出

log("Hello World");
//^--- log must be a macro if we want this __LINE__ in the log
Run Code Online (Sandbox Code Playgroud)

两者都非常不方便,因为要么用户必须在每次调用时传递必须相同的参数,要么我们需要使用具有所有已知缺点的宏。我们source_location可以log("Hello World");不涉及任何宏,但仍然包含调用的行和文件,因为默认参数在调用站点被替换。例如:

#include <source_location>
#include <string>
#include <iostream>

void log(std::string message,const std::source_location& location = std::source_location::current())
{
    std::cout << "Debug:"
              << location.file_name() << ':'
              << location.line() << ' '
              << message << '\n';
}


int main() {
    log("hello");
    log("world");
}
Run Code Online (Sandbox Code Playgroud)

输出

Debug:/app/example.cpp:15 hello
Debug:/app/example.cpp:16 world
Run Code Online (Sandbox Code Playgroud)


Hol*_*Cat 7

在 C++20 之前,您必须在冗长(手动将__LINE__, __FILE__,传递__func__给每个调用)和使用宏为您做这件事之间做出选择。

std::source_location给你一个很好的调用语法,没有宏。没有其他隐藏的优势。

  • @AyxanHaqverdili 你不能模仿标准 C++ 中的 `std::source_location::current()` 。没有 GCC 的 __builtin_LINE()` 或等效函数就不行。 (7认同)
  • @AyxanHaqverdili `std::source_location` 需要编译器支持才能工作。它无法用纯 C++ 实现。 (2认同)
  • @Sneftel 我最初误解了答案。我认为重点是它是一种包装精美的类型。看起来重点是你不需要输入 `__LINE__` 和其他冗长的宏。 (2认同)