33

What is the reasoning to why static const members cannot exist in local classes? It seems like a rather silly restriction.

Example:

void foo() {
  struct bar {
    int baz() { return 0; }   // allowed
    static const int qux = 0; // not allowed?!?
  };
}

struct non_local_bar {
  int baz() { return 0; }   // allowed
  static const int qux = 0; // allowed
};

Quote from standard (9.8.4):

A local class shall not have static data members.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
Pubby
  • 51,882
  • 13
  • 139
  • 180
  • possible duplicate of http://stackoverflow.com/questions/370283/why-cant-i-have-a-non-integral-static-const-member-in-a-class – JosephH Nov 17 '11 at 06:36
  • 2
    @JosephH This might be a duplicate, although the one you linked is asking something else. – Pubby Nov 17 '11 at 06:39
  • Iirc the spec has a footnote on that rule.explaining the reason – Johannes Schaub - litb Nov 17 '11 at 06:39
  • If someone like me come here because of an error prompt of the compiler and have no idea how to identify the bugs. em... you can also try to verify your header files. I accidently put a `{` at the end of one function declaration. ... ... Hoping this may help you :))) – Xin Cheng Apr 30 '19 at 20:22

4 Answers4

28

From the standard section 9.4.2:

If a static data member is of const integral or const enumeration type, its declaration in the class definition can specify a constant-initializer which shall be an integral constant expression. In that case, the member can appear in integral constant expressions within its scope. The member shall still be defined in a namespace scope if it is used in the program and the namespace scope definition shall not contain an initializer.

Basically, local classes have no linkage, and static data members require a linkage.

Since there's no way to define a static data member of a local class in namespace scope (a declaration with an initializer is not a definition), they are not allowed, whether they are of const integral type or not. On the surface it may seem like the compiler should just be able to inline the value, but then what happens if you try to access a pointer to the member? With namespace scoped classes you'd just get a linker error, but local classes have no linkage.

I guess in theory they could just allow you to use static const integral types in local classes as long as they are only used in integral constant expressions, but it would probably just put too much of a burden on the standards body and compiler vendors to differentiate for very little practical value; local static variables are accessible from local classes, so using a local static const should be just as good.

Gerald
  • 23,011
  • 10
  • 73
  • 102
5

I dont think there is a.reason. Normal static datamembers are disallowed because there is no way to define them after being declared.

Also dont forget you can create a local const variable outside the.class that you can use inside the class as long as you only read its value (that is, as long as you dont take.its.address).

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
3

Static members of a class need to be defined in global scope, e.g.

  abc.h

   class myClass {
   static int number;
  };
     abc.cpp

   int myClass::number = 314;

Now, since the scope inside void abc(int x) is not global, there is no scope to define the static member.

Hemant Metalia
  • 29,730
  • 18
  • 72
  • 91
  • `static const` members can be defined inside non-local class definitions. – Pubby Nov 17 '11 at 06:34
  • 3
    They cannot be defined. the inclass initialization is not a definition – Johannes Schaub - litb Nov 17 '11 at 06:38
  • 1
    Static const members declared and initialized inside namespace scoped classes can be used without an external definition as long as they are never used as an l-value (requires an address). If you try to pass them to a function or method that takes a reference or pointer, you will (should) get a linker error. – Gerald Nov 17 '11 at 07:49
-1

As things progress, we now have C++11 and with that you can define integral constants variable members in your classes.

class test
{
public:
    const int FOO = 123;

    [...snip...]
};

That works when you compile with C++11. Notice that the static keyword is not used. When compiling with optimizations turned on, those variables will likely all get optimized out. In debug, though, they appear in your structure as regular variable members.

Note, however, that the size of the class/structure will still include that variable. So here it is likely 4 bytes for the variable FOO.

However, in most cases, classes defined in a function will completely be optimized out so this is a great way of doing things (a good 50% of my classes have such variable members!)

Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156