Title
Definition of "use" in local and nested classes
Status
cd1
Section
12.4 [class.local]
Submitter
Erwin Unruh

Created on 2000-01-27.00:00:00 last changed 143 months ago

Messages

Date: 2003-04-15.00:00:00

[Voted into WP at April 2003 meeting.]

Date: 2002-10-15.00:00:00

Proposed Resolution (revised October 2002):

In 12.2 [class.mem] paragraph 9, replace

Except when used to form a pointer to member (8.3.1 [expr.unary.op]), when used in the body of a nonstatic member function of its class or of a class derived from its class (12.2.2 [class.mfct.non-static]), or when used in a mem-initializer for a constructor for its class or for a class derived from its class (15.6.2 [class.base.init]), a nonstatic data or function member of a class shall only be referred to with the class member access syntax (8.2.5 [expr.ref]).

with the following paragraph

Each occurrence in an expression of the name of a nonstatic data member or nonstatic member function of a class shall be expressed as a class member access (8.2.5 [expr.ref]), except when it appears in the formation of a pointer to member (8.3.1 [expr.unary.op]), when it appears in the body of a nonstatic member function of its class or of a class derived from its class (12.2.2 [class.mfct.non-static]), or when it appears in a mem-initializer for a constructor for its class or for a class derived from its class (15.6.2 [class.base.init]).

In 12.2.5 [class.nest] paragraph 1, replace the last sentence,

Except by using explicit pointers, references, and object names, declarations in a nested class can use only type names, static members, and enumerators from the enclosing class.

with the following

[Note: In accordance with 12.2 [class.mem], except by using explicit pointers, references, and object names, declarations in a nested class shall not use nonstatic data members or nonstatic member functions from the enclosing class. This restriction applies in all constructs including the operands of the sizeof operator.]

In the example following 12.2.5 [class.nest] paragraph 1, change the comment on the first statement of function f to emphasize that sizeof(x) is an error. The example reads in full:

  int x;
  int y;
  class enclose {
  public:
    int x;
    static int s;
    class inner {
      void f(int i)
      {
        int a = sizeof(x);  // error: direct use of enclose::x even in sizeof
        x = i;              // error: assign to enclose::x
        s = i;              // OK: assign to enclose::s
        ::x = i;            // OK: assign to global x
        y = i;              // OK: assign to global y
      }
      void g(enclose* p, int i)
      {
        p->x = i;        // OK: assign to enclose::x
      }
    };
  };

  inner* p = 0;             // error: inner not in scope
Date: 2002-04-15.00:00:00

Notes from the 4/02 meeting:

We backed away from "use" in the technical sense, because the requirements on the form of reference are the same whether or not the reference occurs inside a sizeof.

Date: 2001-10-15.00:00:00

Notes from 10/01 meeting:

It was noted that the suggested resolution did not make the sizeof() example in 12.2.5 [class.nest] valid. Although the reference to the argument of sizeof() is not regarded as a use, the right syntax must be used nonetheless to reference a non-static member from the enclosing class. The use of the member name by itself is not valid. The consensus within the core working group was that nothing should be done about this case. It was later discovered that 12.2.3 [class.static] paragraph 3 states that

The definition of a static member shall not use directly the names of the nonstatic members of its class or of a base class of its class (including as operands of the sizeof operator). The definition of a static member may only refer to these members to form pointer to members (8.3.1 [expr.unary.op]) or with the class member access syntax (8.2.5 [expr.ref]).

This seems to reinforce the decision of the working group.

The use of "use" should still be cross-referenced. The statements in 12.2.5 [class.nest] and 12.4 [class.local] should also be rewritten to state the requirement positively rather than negatively as the list of "can't"s is already missing some cases such as template parameters.

Date: 2004-09-10.00:00:00

12.4 [class.local] paragraph 1 says,

Declarations in a local class can use only type names, static variables, extern variables and functions, and enumerators from the enclosing scope.
The definition of when an object or function is "used" is found in 6.2 [basic.def.odr] paragraph 2 and essentially says that the operands of sizeof and non-polymorphic typeid operators are not used. (The resolution for issue 48 will add contexts in which integral constant expressions are required to the list of non-uses.)

This definition of "use" would presumably allow code like

    void foo() {
        int i;
        struct S {
            int a[sizeof(i)];
        };
    };
which is required for C compatibility.

However, the restrictions on nested classes in 12.2.5 [class.nest] paragraph 1 are very similar to those for local classes, and the example there explicitly states that a reference in a sizeof expression is a forbidden use (abbreviated for exposition):

    class enclose {
    public:
        int x;
        class inner {
            void f(int i)
            {
                int a = sizeof(x);  // error: refers to enclose::x
            }
        };
    };

[As a personal note, I have seen real-world code that was exactly like this; it was hard to persuade the author that the required writearound, sizeof(((enclose*) 0)->x), was an improvement over sizeof(x). —wmm]

Similarly, 12.2 [class.mem] paragraph 9 would appear to prohibit examples like the following:

    struct B {
        char x[10];
    };
    struct D: B {
        char y[sizeof(x)];
    };

Suggested resolution: Add cross-references to 6.2 [basic.def.odr] following the word "use" in both 12.2.5 [class.nest] and 12.4 [class.local] , and change the example in 12.2.5 [class.nest] to indicate that a reference in a sizeof expression is permitted. In 12.2 [class.mem] paragraph 9, "referred to" should be changed to "used" with a cross_reference to 6.2 [basic.def.odr].

History
Date User Action Args
2008-10-05 00:00:00adminsetstatus: wp -> cd1
2003-04-25 00:00:00adminsetmessages: + msg866
2003-04-25 00:00:00adminsetstatus: ready -> wp
2002-11-08 00:00:00adminsetstatus: review -> ready
2002-05-10 00:00:00adminsetmessages: + msg624
2002-05-10 00:00:00adminsetmessages: + msg623
2001-11-09 00:00:00adminsetmessages: + msg559
2001-11-09 00:00:00adminsetstatus: drafting -> review
2000-05-21 00:00:00adminsetstatus: open -> drafting
2000-01-27 00:00:00admincreate