Title
Inconsistencies in the descriptions of constant expressions
Status
tc1
Section
7.7 [expr.const]
Submitter
Mike Miller

Created on 1999-02-08.00:00:00 last changed 254 months ago

Messages

Date: 2004-09-10.00:00:00
  1. According to 11.4.9.3 [class.static.data] paragraph 4, a static const integral or const enumeration data member initialized with an integral constant expression "can appear in integral constant expressions within its scope" [emphasis mine]. This means that the following is not permitted:
        struct S {
            static const int c = 5;
        };
        int a[S::c];    // error: S::c not in scope
    
    Is this restriction intentional? If so, what was the rationale for the restriction?

    Bjarne Stroustrup: I think that once you have said S::, c is in scope so that

        int a[S::c];
    
    is ok.

    Mike Miller: I'd like to think that's what it meant, but I don't believe that's what it said. According to 6.4 [basic.scope] paragraph 1, the scope of a name is the region "in which that name may be used as an unqualified name." You can, indeed, use a qualified name to refer to a name that is not in scope, but that only goes to reinforce my point that "S::c" is not in scope at the point where the expression containing it is used. I think the phrase "within its scope" is at best misleading and should be removed. (Unless there's a reason I'm missing for restricting the use of static member constants to their scope.)

  2. According to 7.7 [expr.const] paragraph 1, integral constant expressions can "involve...const variables or static data members of integral or enumeration types initialized with constant expressions." However, in 7.7 [expr.const] paragraph 3, arithmetic constant expressions cannot include them. This seems a rather gratuitous distinction and one likely to bite programmers trained always to use const variables instead of preprocessor definitions. Again, is there a rationale for the difference?

    As far as I can tell from 7.7 [expr.const] paragraph 2, "arithmetic constant expressions" (as distinct from "integral constant expressions") are used only in static initializers to distinguish between static and dynamic initialization. They include floating point types and exclude non-type template parameters, as well as the const variables and static data members.

  3. There is a minor error in 7.7 [expr.const] paragraph 2. The first sentence says, "Other expressions are considered constant expressions only for the purpose of non-local static object initialization." However, 8.8 [stmt.dcl] paragraph 4 appears to rely on the same definition dealing with the initialization of local static objects. I think that the words "non-local" should be dropped and a cross reference to 8.8 [stmt.dcl] added.

  4. 7.7 [expr.const] paragraph 4 says, "An expression that designates the address of a member or base class of a non-POD class object (clause 9) is not an address constant expression (11.9.5 [class.cdtor] )."

    I'm guessing that should be "non-static member," like the similar prohibition in 11.9.5 [class.cdtor] regarding out-of-lifetime access to members of non-POD class objects.

Proposed resolutions (10/00):

  1. Remove the phrase "within its scope" in 11.4.9.3 [class.static.data] paragraph 4.

  2. Replace 7.7 [expr.const] paragraph 3 with the following:
    An arithmetic constant expression shall satisfy the requirements for an integral constant expression, except that
    • floating literals need not be cast to integral or enumeration type, and
    • conversions to floating point types are permitted.
  3. This is not a defect; no change is required. The suggested wording would be more accurate, but since the effect on local initialization is unobservable the current wording is adequate.

  4. Change the referenced sentence in 7.7 [expr.const] paragraph 4 to "An expression that designates the address of a subobject of a non-POD class object is not an address constant expression."

History
Date User Action Args
2003-04-25 00:00:00adminsetstatus: dr -> tc1
2000-11-18 00:00:00adminsetstatus: ready -> dr
2000-05-21 00:00:00adminsetstatus: drafting -> ready
1999-02-08 00:00:00admincreate