source_location::current() оценивается как аргумент шаблона без типа по умолчанию
[support.srcloc] представляет
source_location::current
:
Любой звонок
current
который появляется как аргумент по умолчанию ([dcl.fct.default]) или как его подвыражение, должен соответствовать местоположению вызова функции, которая использует аргумент по умолчанию ([expr.call]).
Обратите внимание, что "аргумент по умолчанию ( [dcl.fct.default])" включает аргумент шаблона по умолчанию, но в приведенной выше цитате упоминается только "место вызова функции". Будет ли законно оценивать
source_location::current()
в контексте аргумента шаблона по умолчанию?
Рассмотрим этот код ( Live Demo):
#include <iostream>
//#include <source_location>
#include <experimental/source_location>
//using source_location = std::source_location;
using source_location = std::experimental::source_location;
struct literal {
char data[64] = {'\0'}; // For simplicity, assume it is large enough to hold all possible values.
constexpr literal(const char* src) {
char* dst = &data[0];
while(*src) *(dst++) = *(src++);
*dst = '\0';
}
};
struct location { // A structural type is needed since source_location is not a structural type.
literal file;
literal func;
unsigned line;
unsigned column;
constexpr location(const char* file, const char* func, unsigned line, unsigned column)
: file(file), func(func), line(line), column(column) {}
constexpr location(const source_location& loc)
: location(loc.file_name(), loc.function_name(), loc.line(), loc.column()) {}
};
template<location loc = source_location::current()> // line 30
void print() {
std::cout << loc.file.data << ' ' << loc.func.data << ' ' << loc.line << ' ' << loc.column << std::endl;
}
void caller_1() {
print(); // line 36
}
void caller_2() {
print(); // line 40
}
int main() {
caller_1();
caller_2();
return 0;
}
clang не компилируется с ошибкой:
ошибка: извините, не типовой аргумент шаблона типа "местоположение" еще не поддерживается
gcc заставляет его компилироваться, но дает странный результат:
function_name()
и
line()
указать разные места:
./example.cpp caller_1 30 0
./example.cpp caller_2 30 0