source_location::current() evaluated as default non-type template argument

474 views Asked by At

[support.srcloc] introduces source_location::current:

Any call to current that appears as a default argument ([dcl.fct.default]), or as a subexpression thereof, should correspond to the location of the invocation of the function that uses the default argument ([expr.call]).

Note that "default argument ([dcl.fct.default])" includes default template argument but the above quote only metioned "the location of the invocation of the function". Will it be legal to evaluate source_location::current() in a context of default template argument?

Consider this code (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 fails to compile with an error:

error: sorry, non-type template argument of type 'location' is not yet supported

gcc makes it to be compiled but gives weird result that function_name() and line() indicate different locations:

./example.cpp caller_1 30 0

./example.cpp caller_2 30 0

0

There are 0 answers