5

在 C++20 中添加了一个新功能来获取源位置信息:https ://en.cppreference.com/w/cpp/utility/source_location

这是该页面的一个稍作修改的示例,其中使用了添加立即函数loc来获取源位置:

#include <iostream>
#include <string_view>
#include <source_location>
 
consteval auto loc(std::source_location x = std::source_location::current() ) { return x; }

void log(const std::string_view message,
         const std::source_location location = loc()) {
    std::cout << "file: "
              << location.file_name() << "("
              << location.line() << ":"
              << location.column() << ") `"
              << location.function_name() << "`: "
              << message << '\n';
}
 
template <typename T> void fun(T x) { log(x); }
 
int main(int, char*[]) {
    log("Hello world!");
    fun("Hello C++20!");
}

在最新的 MSVC 2019 中,它的打印结果与 cppreference.com 的原始示例一样:

file: main.cpp(25:5) `main`: Hello world!
file: main.cpp(20:5) `fun`: Hello C++20!

但在 GCC 中,同一行在输出中显示了两次:

file: /app/example.cpp(8:51) ``: Hello world!
file: /app/example.cpp(8:51) ``: Hello C++20!

演示:https ://gcc.godbolt.org/z/nqE4cr9d4

哪个编译器在这里?

如果定义loc函数不是立即函数:

auto loc(std::source_location x = std::source_location::current() ) { return x; }

然后 GCC 的输出发生变化并类似于原始示例:

file: /app/example.cpp(20:8) `int main(int, char**)`: Hello world!
file: /app/example.cpp(17:42) `void fun(T) [with T = const char*]`: Hello C++20!

虽然 MSVC 拒绝编译它并出现错误:

error C7595: 'std::source_location::current': call to immediate function is not a constant expression

演示:https ://gcc.godbolt.org/z/vorW4f9ax

还请建议,哪个编译器在非即时情况下也是正确的?

4

1 回答 1

3

这在17.8.2.1.2[support.srcloc.class](强调我的)中进行了解释:

备注:对它的任何调用都current显示为默认成员初始化程序 (11.4) 或其子表达式,应对应于使用默认成员初始化程序的构造函数定义或聚合初始化的位置。对它的任何调用都current显示为默认参数 (9.3.3.6) 或其子表达式,应对应于使用默认参数 (7.6.1.2) 的函数的调用位置

由此,我推断 GCC 是对的。

当调用current发生在第 5 行时,它返回一个source_location对象,该对象“对应 [s] 到 使用默认参数的函数(在本例中为函数loc调用的位置” 。

在这种情况下,调用位置是8:51(表达式const std::source_location location = loc())。

为什么函数名是空的,解释如下:

  1. 17.8.2.1.1.1(表 38)告诉我们函数名应该是“如 in” __func__
元素 价值
function_name_ 当前函数的名称,如__func__(9.5.1) 中的名称(如果有),否则为空字符串。
  1. 9.5.1.8 示例表明,如果__func__作为默认参数出现,则名称未定义。我知道示例是非规范性文本,但这清楚地描述了意图:

[例子:

struct S {
S() : s(__func__) { } // OK
const char* s;
};
void f(const char* s = __func__); // error: __func__ is undeclared

——结束示例]

于 2021-08-13T11:42:00.110 回答