consteval如何影响默认实参求值?其与constexpr/运行时行为差异根源?
关于consteval与默认实参、source_location的问题解答
问题1:consteval 如何影响默认实参的求值?
consteval是C++20引入的立即函数,它的核心要求是:调用必须是常量表达式,必须在编译阶段完成求值。这直接改变了默认实参的求值逻辑:
- 对于普通函数(或constexpr函数)的调用作为默认实参,求值时机是函数调用点:每次调用目标函数时,才会计算默认实参的值,求值上下文是调用代码所在的位置。
- 当默认实参是consteval函数的调用时,由于必须在编译期完成求值,这个调用会在默认实参被声明的位置(也就是目标函数的参数列表定义处)执行,而不是等到函数被调用的时候。毕竟编译期求值没法延迟到运行时的调用点,所以只能在默认实参的定义上下文里完成计算。
问题2:source_location行号差异的根源是什么?
先看你给出的代码示例:
#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(); }
这种行号差异的核心,就是consteval函数的求值上下文和普通/constexpr函数完全不同:
当here()是consteval时
consteval要求调用必须在编译期完成,所以默认实参here()的求值发生在f()的参数声明处(也就是代码里here()作为默认实参被写出来的那一行)。此时std::experimental::source_location::current()会记录这个编译期求值位置的源代码信息,也就是f()参数定义处的行号,所以最终输出的是类似10的数值。
当here()改为constexpr或普通运行时函数时
默认实参的求值时机切换到了函数调用点——也就是main()里调用f()的那一行。此时source_location::current()会抓取调用f()的位置信息,自然就输出main函数里调用行的行号(比如示例里的17)。
简单说就是:consteval把默认实参的求值“提前”到了函数定义阶段,而普通函数则是“延迟”到了调用阶段,这直接导致了source_location获取的位置完全不同。
内容的提问来源于stack exchange,提问作者Marcin Zdun
相关产品推荐
相关产品推荐

