source_location调用结果存差异,C++标准规定的正确结果(含wrapper)是什么?
C++标准下
source_location的正确行为分析 测试代码
// Preamble #include <iostream> #include <source_location> // Using a function constexpr std::size_t function( std::size_t line = std::source_location::current().line() ) noexcept {return line;} // Using a constructor struct construction { constexpr construction( std::size_t input = std::source_location::current().line() ) noexcept: line{input} {} std::size_t line; }; // Using a template deduction guide template <std::size_t Line> struct wrapper { static constexpr std::size_t line = Line; }; template <std::size_t index = std::source_location::current().line()> wrapper() -> wrapper<index>; // Main int main(int argc, char* argv[]) { std::size_t f1 = function(); std::size_t f2 = function(); std::size_t c1 = construction().line; std::size_t c2 = construction().line; std::size_t w1 = wrapper().line; std::size_t w2 = wrapper().line; std::cout << f1 << " " << f2 << std::endl; std::cout << c1 << " " << c2 << std::endl; std::cout << w1 << " " << w2 << std::endl; return 0; }
不同编译器输出
// GCC 12.2 28 29 // NOT EQUAL 30 31 // NOT EQUAL 23 23 // EQUAL // CLANG 15.0 7 7 // EQUAL 13 13 // EQUAL 23 23 // EQUAL
标准规定的正确输出
根据C++20及后续标准的规定,正确输出应与GCC的结果一致:
f1和f2分别对应调用function()的行号(代码第28、29行),输出28 29c1和c2分别对应调用construction()的行号(代码第30、31行),输出30 31w1和w2为同一个值,即推导指南定义所在的行号(代码第23行),输出23 23
规则细节解释
函数/构造函数的默认参数:
std::source_location::current()作为函数默认参数时,求值时机是每次函数被调用时,会获取当前调用语句所在的行号。因此每次调用function()或construction(),都会取对应调用行的行号,所以f1≠f2、c1≠c2,GCC的行为符合标准,Clang此处处理有误。模板推导指南的默认模板参数:
模板推导指南中的默认模板参数,求值时机是模板首次被实例化时,而非每次调用。这里wrapper()推导指南里的index默认值,会在第一次创建wrapper对象时,取推导指南定义所在的行号(第23行),后续所有wrapper()调用都会复用该实例化结果,因此w1和w2值相同,GCC与Clang的这部分行为都符合标准。
内容的提问来源于stack exchange,提问作者Vincent
相关产品推荐
相关产品推荐

