编译时的std::experimental::source_location

8

std::experimental::source_location将来可能会被添加到C++标准中。我想知道是否可能将位置信息传递到编译时领域。本质上,当从不同的源位置调用时,我想要一个返回不同类型的函数。像这样的一些东西,尽管它不能编译,因为location对象不是constexpr作为函数参数:

#include <experimental/source_location>

using namespace std::experimental;

constexpr auto line (const source_location& location = source_location::current())
{
  return std::integral_constant<int, location.line()>{};
}

int main()
{
  constexpr auto ll = line();
  std::cout << ll.value << '\n';
}

这段代码无法编译,会提示相关错误信息

expansion of [...] is not a constant expression

关于return std::integral_constant<int, location.line()>{}这一行。如果我无法使用source_location的方法,那么它们是constexpr有什么好处呢?


这与std::experimental::source_location没有任何关系。line函数是constexpr的,但它的参数不是constexpr的。函数参数从来都不是constexpr的。在C++20中,我们可以将任意类型作为模板参数,因此source_location可能是一个模板参数。 - Justin
2
经进一步调查,这实际上是一个有趣的问题。获取source_location对象的后期构建的唯一方法是使用默认函数参数。默认的模板参数不起作用;它是早期创建的,而不是晚期。这可能是一个疏忽。constexpr函数参数可以解决问题,但目前这个想法并不太受欢迎。 - Justin
1个回答

8

正如Justin所指出的那样,您代码中的函数参数不是constexpr。但更有用地在constexpr函数中使用source_location的问题已在constexpr!函数提案中提到:

The "Library Fundamentals v. 2" TS contains a "magic" source_location class get to information similar to the FILE and LINE macros and the func variable (see N4529 for the current draft, and N4129 for some design notes). Unfortunately, because the "value" of a source_location is frozen at the point source_location::current() is invoked, composing code making use of this magic class is tricky: Typically, a function wanting to track its point of invocation has to add a defaulted parameter as follows:

void my_log_function(char const *msg,
                     source_location src_loc
                        = source_location::current()) {
  // ...
}

This idiom ensure that the value of the source_location::current() invocation is sampled where my_log_function is called instead of where it is defined.

Immediate (i.e., constexpr!) functions, however, create a clean separation between the compilation process and the constexpr evaluation process (see also P0992). Thus, we can make source_location::current() an immediate function, and wrap it as needed in other immediate functions: The value produced will correspond to the source location of the "root" immediate function call. For example:

constexpr! src_line() {
  return source_location::current().line();
}

void some_code() {
  std::cout << src_line() << '\n';  // This line number is output.
}

目前这是一个未解决的问题。

在IT技术方面。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接