consteval 如何影响默认参数的评估?

Mar*_*dun 6 c++ constexpr c++20 consteval

在下面的代码中,如果here()停止consteval(完整 RT 或constexpr),则line()f()inside的调用行main()。但有了consteval它的定义f()。这种差异从何而来?

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

consteval std::experimental::source_location here(
    std::experimental::source_location loc = std::experimental::source_location::current())
{
   return loc;
}

void f(const std::experimental::source_location& a = here())
{
   std::cout << a.line() << std::endl; // will either print 17, or 10
}

int main()
{
   f();
}
Run Code Online (Sandbox Code Playgroud)

Godbolt 链接

Ann*_*nyo 0

这是我的理解:

默认参数在调用站点替换并在每次调用时进行评估。请参阅以下代码作为示例:

#include <iostream>

int count() {
    static int counter = 0;
    return ++counter;
}

void foo(int value = count())
{
    std::cout << value << "\n";
}

int main()
{
   foo();
   foo();
}
Run Code Online (Sandbox Code Playgroud)

见神螺栓

输出是

1
2
Run Code Online (Sandbox Code Playgroud)

这证明count()已被调用两次,并且main()主体实际上相当于:

1
2
Run Code Online (Sandbox Code Playgroud)

现在让我们回到你的例子。如果here()不是consteval,那么您的调用f()相当于,而这f(here())又相当于f(here(std::experimental::source_location::current())),这将返回调用的行f(),即是17

然而,如果here()is consteval,当编译器读取 的声明时f(),它必须立即计算here()which 返回某个此时等于std::experimental::source_locationline()值(为了解释的目的,我们称其为),因此当您调用 时,默认参数已经被计算为,并且该调用实际上相当于10default_locationf()default_locationf(default_location)