This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-11-11


2835. Name-independent declarations

Section: 6.4.1  [basic.scope.scope]     Status: open     Submitter: Jakub Jelínek     Date: 2023-11-30

The wording for name-independent declarations applied by P2169R4 (A nice placeholder with no name) apparently fails to implement the intent.

Consider:

  void foo () { auto c = [_ = 2, _ = 3] () {}; }   // duplicate identifier in lambda-capture

  struct S { int _; int _; };  // repeated member declaration

  void f() {
    if (int _ = 5) {    // #1
      int _ = 6;        // #2
      int k = _;        // ambiguous lookup despite #1 and #2 in different scopes?
    } else {
       int _ = 7;
    }
  }

Possible resolution (first two issues):

  1. Change in 7.5.6.3 [expr.prim.lambda.capture] paragraph 2 as follows:

    ... A capture name is an identifier or this. Ignoring appearances in initializers of init-captures, an identifier or this shall not appear more than once the program is ill formed if the appearance of a capture name precedes another appearance of the same capture name in a lambda-capture, and the latter is not a name-independent declaration (6.4.1 [basic.scope.scope]). [ Example 1:
      struct S2 { void f(int i); };
      void S2::f(int i) {
        [&, i]{ };  // OK
        [&, this, i]{ }; // OK, equivalent to [&, i]
        [&, &i]{ };      // error: i preceded by & when & is the default
        [=, *this]{ };   // OK
        [=, this]{ };    // OK, equivalent to [=]
        [i, i]{ };       // error: i repeated
        int _ = 17;
        [_, _ = 42]{ };      // OK
        [this, *this]{ }; // error: this appears twice
      }
    
    --end example ]
  2. Change in 11.4.1 [class.mem.general] paragraph 5 as follows:

    A member shall not be declared twice in the member-specification, except that
    • a nested class or member class template can be declared and then later defined, and
    • an enumeration can be introduced with an opaque-enum-declaration and later redeclared with an enum-specifier.
    [Note 3: A single name can denote several member functions provided their types are sufficiently different (6.4.1 [basic.scope.scope]). Repeated name-independent declarations declare different members.end note]

CWG 2023-12-15

Having a lookup ambiguity for the third case (int k = _;) seems consistent with the idea that #1 and #2 are considered to be in the same scope as far as name conflict detection is concerned. However, that would need new rules, given that name lookup does not proceed to outer scopes when a name is found in an inner scope. Similar lookup ambiguities across nested scopes can arise among lambda captures, template parameters of a lambda, lambda function parameters, and declartions in the outermost block scope of a lambda.