This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.

4207. Point of reference for source_location is not specified when used in an default template argument

Section: 17.8.2.2 [support.srcloc.cons] Status: New Submitter: Cassio Neri Opened: 2025-02-07 Last modified: 2025-02-07

Priority: Not Prioritized

View all other issues in [support.srcloc.cons].

View all issues with New status.

Discussion:

17.8.2.2 [support.srcloc.cons]/2 in N5001 says nothing about using source_location::current() in an initializer of a template parameter. The example below suggests that gcc, clang and msvc seem to agree on this case. It would be nice if the Standard legitimized current practice.


#include <source_location>

template <int i = std::source_location::current().line()> // line 3
struct A {
  static constexpr int value = i;
};

template <int i = std::source_location::current().line()> // line 8
constexpr int f() {
  return i;
}

static_assert(A<>::value == 3); // passes
static_assert(f() == 8); // passes

[2025-02-07; Jonathan provides wording]

For a default argument of a function parameter, current() is recommended to return the location of the caller that makes use of that default argument. For a default template argument, the location would be determined by the template's point of instantiation (13.8.4.1 [temp.point]) which would not always do what users expect. Using the location of the default template argument in the template declaration seems sensible and predictable, and matches existing practice. Arguably, this doesn't need to be stated because it's just "exactly where the current() call appear in the source". The other cases in the Remarks paragraph are situations where the preferred location is different, because we want to know where it's used, not defined.

Proposed resolution:

This wording is relative to N5001.

  1. Modify 17.8.2.2 [support.srcloc.cons] as indicated:
    -2- Remarks: Any call to current that appears as a default member initializer (11.4 [class.mem]), or as a subexpression thereof, should correspond to the location of the constructor definition or aggregate initialization that uses the default member initializer. Any call to current that appears as a default argument (9.3.4.7 [dcl.fct.default]), or as a subexpression thereof, should correspond to the location of the invocation of the function that uses the default argument (7.6.1.3 [expr.call]). Any call to current that appears as a default template argument (13.2 [temp.param]), or as a subexpression thereof, should correspond to the location where the default template argument is specified.