17
void foo (int x)
{
  struct A { static const int d = 0; }; // error
}

Other than the reference from standard, is there any motivation behind this to disallow static field inside an inner class ?

error: field `foo(int)::A::d' in local class cannot be static

Edit: However, static member functions are allowed. I have one use case for such scenario. Suppose I want foo() to be called only for PODs then I can implement it like,

template<typename T>
void foo (T x)
{
  struct A { static const T d = 0; }; // many compilers allow double, float etc.
}

foo() should pass for PODs only (if static is allowed) and not for other data types. This is just one use case which comes to my mind.

iammilind
  • 68,093
  • 33
  • 169
  • 336
  • 1
    Possible duplicate [static member variable inside a local class in c++?](http://stackoverflow.com/questions/2012745/static-member-variable-inside-a-local-class-in-c) – dee-see May 26 '11 at 10:51
  • 1
    @Vache: I don't think that's a dup (from some of the OP's comments there). – sje397 May 26 '11 at 10:54

6 Answers6

6

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

foo.h

class A {
  static int dude;
};

foo.cpp

int A::dude = 314;

Since the scope inside void foo(int x) is local to that function, there is no scope to define its static member[s].

iammilind
  • 68,093
  • 33
  • 169
  • 336
rtn
  • 127,556
  • 20
  • 111
  • 121
  • 1
    how can it be a global scope when you can declare a `static` variable simply inside a function ? [Note: I have not downvoted but, before it goes out of control, I suggest to edit your answer.] – iammilind May 26 '11 at 10:56
  • @iammilind: that's precisely the problem. If this were allowed, the member would have to be, but cannot be defined in the global scope. Since the _definition_ is impossible, the standard made the _declaration_ illegal. That means you get the error already at compile time, not link time. – MSalters May 26 '11 at 13:00
  • Thanks for backing me up Salters :D – rtn May 26 '11 at 13:08
  • @MSalters, I now realized @Magnus answer is more precise. But due to lack of description, someone downvoted it. @Magnus can you detail a bit more for others to understand. I will accept the answer. Thanks both. – iammilind May 26 '11 at 13:43
  • @iammilind: I revised my answer a bit. Let me know if you want me to be more precise. – rtn May 26 '11 at 14:08
5

Magnus Skog has given the real answer: a static data member is just a declaration; the object must be defined elsewhere, at namespace scope, and the class definition isn't visible at namespace scope.

Note that this restriction only applies to static data members. Which means that there is a simple work-around:

class Local
{
    static int& static_i()
    {
        static int value;
        return value;
    }
};

This provides you with exactly the same functionality, at the cost of using the function syntax to access it.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • Is this exactly the same? IIRC the address of a static class member is a valid non-type template argument, and this obviously isn't. – MSalters May 26 '11 at 14:06
  • +1, your answer is very much explanatory and thanks for the work around too. I wish I can accept 2 answers. :) – iammilind May 26 '11 at 14:20
  • @MSalters Good point, at least partially. A static integral const with an initializer would be an integral constant expression, which could be used as a non-type template argument, or a dimension for a C style array. For other static members, I think you'd hit the requirement that the object have external linkage, which isn't the case for local classes or their members. – James Kanze May 27 '11 at 11:24
4

Because nobody saw any need for it ?

[edit]: static variables need be defined only once, generally outside of the class (except for built-ins). Allowing them within a local class would require designing a way to define them also. [/edit]

Any feature added to a language has a cost:

  • it must be implemented by the compiler
  • it must be maintained in the compiler (and may introduce bugs, even in other features)
  • it lives in the compiler (and thus may cause some slow down even when unused)

Sometimes, not implementing a feature is the right decision.

Local functions, and classes, add difficulty already to the language, for little gain: they can be avoided with static functions and unnamed namespaces.

Frankly, if I had to make the decision, I'd remove them entirely: they just clutter the grammar.

A single example: The Most Vexing Parse.

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
  • @Matthieu, I have mentioned one use case. just for info. – iammilind May 26 '11 at 12:24
  • 2
    First, local classes have no relationship to the "Most Vexing Parse". And they're extremely useful; the real problem is that you couldn't use them to instantiate a template. – James Kanze May 26 '11 at 13:06
  • On it's own, this answer is clearly wrong. After all, once the decisions to support local classes was made, additional limitations complicate the grammar, not simplify it. However, combined with the other answers, it does a good job of explaining why they removed the feature rather than find a solution to it's shortcomings. – Dennis Zickefoose May 26 '11 at 13:32
  • "Adding a feature has a cost" - But currently it's more of an anti-feature. That is to say, the compiler has to detect and reject this special case, and that too has a cost. You could also have added a non-mandatory note to the standard "The syntax allows such members, but since you can't define them they're generally useless". Such a non-feature would be even cheaper to implement than this anti-feature. – MSalters May 26 '11 at 14:05
  • @James: I didn't said that local classes had a relation with the most vexing parse, and I would argue that they are not really necessary since you have unnamed namespaces. In C++0x and with lambdas, they really become anecdotal. – Matthieu M. May 26 '11 at 14:52
  • 1
    @Dennis, @MSalters: but static data members need be defined (normally outside the class scope), which would require yet another syntax / grammar rule. – Matthieu M. May 26 '11 at 15:01
  • Right. Which is why I said on it's own, this is wrong. This rule removes a feature, not adds one. But in conjunction with other considerations, the cost becomes prohibitive. So this answer is the second half to the full answer. – Dennis Zickefoose May 26 '11 at 18:14
  • @Dennis: ah right, I was so engrossed in my explanation that I got distracted. I've added an edit to mention this. – Matthieu M. May 27 '11 at 06:18
0

I think this is the same naming problem that has prevented us from using local types in template instantiations.

The name foo()::A::d is not a good name for the linker to resolve, so how should it find the definition of the static member? What if there is another struct A in function baz()?

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
  • 2
    Not convincing. After all, function can declare `static` variable, but we don't want to access it as `foo()::static_var` then. Also, we don't want to access even local classes from outside as `foo()::A`, then why `foo()::A::d`? – Nawaz May 26 '11 at 11:18
  • The argument holds, it's indeed a matter of linkage. A variable declared in a function has _no_ linkage, even if it's a `static` variable. But for the definition of a `static` class method, it's necessary to match the declaration and definition, which in turn _does_ require linkage. – MSalters May 26 '11 at 13:06
0

Interesting question, but I have difficulty understanding why you'd want a static member in a local class. Statics are typically used to maintain state across program flow, but in this case wouldn't it be better to use a static variable whose scope was foo()?

If I had to guess why the restriction exists, I'd say it was something to do with the difficulty for the compiler in knowing when to perform the static initialisation. The C++ standards docs might provide a more formal justification.

Andy Johnson
  • 7,938
  • 4
  • 33
  • 50
  • The C++ standard hardly contains any justification; it's typically found in non-normative notes and comments. (It's a big enough document with just the rules; there's a reasonable amount of justification to be found in the public working documents of the C++ committee. ) – MSalters May 26 '11 at 13:08
0

Just because.

One annoying thing about C++ is that there's a strong dependence on a "global context" concept where everything must be uniquely named. Even the nested namespaces machinery is just string trickery.

I suppose (just a wild guess) that one serious technical issue is working with linkers that were designed for C and that just got some tweak to get them working with C++ (and C++ code needs C interoperability).

It would be nice to be able to get any C++ code and "wrap it" to be able to use it without conflicts in a larger project, but this is not the case because of linkage problems. I don't think there is any reasonable philosophical reason for forbidding statics or non-inline methods (or even nested functions) at the function level but this is what we got (for now).

Even the declaration/definition duality with all its annoying verbosity and implications is just about implementation problems (and to give the ability to sell usable object code without providing the source, something that is now a lot less popular for good reasons).

6502
  • 112,025
  • 15
  • 165
  • 265