This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 110b. See for the official list.


94. Inconsistencies in the descriptions of constant expressions

Section: 7.7  [expr.const]     Status: TC1     Submitter: Mike Miller     Date: 8 Feb 1999
  1. According to [] 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 [] 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."