std:: экспериментальный::source_location во время компиляции

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 если я не могу их использовать?

1 ответ

Как указал Джастин, проблема с вашим кодом заключается в том, что аргумент функции не является constexpr, а проблема использования source_location в функции constexpr более полезным образом упоминается в constexpr! предложение функций, которое гласит:

TS "Library Fundamentals v. 2" содержит "волшебный" класс source_location, позволяющий получить информацию, аналогичную макросам FILE и LINE и переменной func (текущий черновик см. В N4529, а в некоторых заметках по проекту - N4129). К сожалению, поскольку "значение" source_location замораживается в точке, вызывается source_location::current(), составление кода с использованием этого магического класса является хитрым: как правило, функция, желающая отследить свою точку вызова, должна добавить параметр по умолчанию следующим образом:

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

Эта идиома гарантирует, что значение вызова source_location::current() выбирается там, где вызывается my_log_function, а не там, где оно определено.

Однако непосредственные функции (то есть constexpr!) Создают четкое разделение между процессом компиляции и процессом оценки constexpr (см. Также P0992). Таким образом, мы можем сделать source_location::current() непосредственной функцией и обернуть ее, как необходимо, в других непосредственных функциях: Полученное значение будет соответствовать исходному расположению непосредственного вызова функции "root". Например:

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

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

Так что это в настоящее время открытая проблема.

Другие вопросы по тегам