Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::experimental::source_location at compile time

std::experimental::source_location will probably be added to the C++ standard at some point. I'm wondering if it possible to get the location information into the compile-time realm. Essentially, I want a function that returns different types when called from different source locations. Something like this, although it doesn't compile because the location object isn't constexpr as it's a function argument:

#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';
}

This doesn't compile, with a message about

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

regarding the return std::integral_constant<int, location.line()>{} line. What good it is to have the methods of source_location be constexpr if I can't use them?

like image 580
Toby Brull Avatar asked Oct 24 '18 20:10

Toby Brull


1 Answers

As Justin pointed the issue with your code is that function argument are not constexpr but the problem of using source_location in a constexpr function in a more useful way is mentioned in the constexpr! functions proposal which says:

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.
}

So this is currently an open problem.

like image 77
Shafik Yaghmour Avatar answered Oct 04 '22 08:10

Shafik Yaghmour