25

C++17 allows static member variables to be defined thus:

class X {
  public:
    static inline int i = 8;
};

What is the rationale behind requiring the inline specification? Why not simply allow programmers to write

    static int i = 8;

in the class?

M.M
  • 138,810
  • 21
  • 208
  • 365
oz1cz
  • 5,504
  • 6
  • 38
  • 58
  • 1
    Check this [question and answer](https://stackoverflow.com/questions/3409428/putting-class-static-members-definition-into-cpp-file-technical-limitation), it can give you some insight into "why". – Sergey.quixoticaxis.Ivanov Oct 22 '17 at 12:36

1 Answers1

18

Without inline, it's explicitly stated as only a declaration. As specified in [class.static.data]/2

The declaration of a non-inline static data member in its class definition is not a definition and may be of an incomplete type other than cv void. The definition for a static data member that is not defined inline in the class definition shall appear in a namespace scope enclosing the member's class definition.

The rationale is most probably to keep legacy code intact and valid. Recall that we could initialize integral constants in the class definition itself since about forever. But odr-using them still required an out-of-class definition in some translation unit.

So to makes such variables implicitly inline could be problematic in existing codebases. The committee is always thinking about backwards compatibility when core language features are added.

For instance, consider this valid C++03 class definition:

struct foo {
    static const int n = 3;
    double bar[n];
};

n can be used as a constant expression to define the extent of bar, and it's not considered an odr-use. Nowadays we'd write it as constexpr1, however that above is still valid. But there may be cases were n would have to be odr-used (imagine its address taken, or a reference bound to it, etc). They are probably not many, and probably not common, but certain API's have crazy requirements that would end up necessitating this

const int foo::n;

to appear in some translation unit.

Now, if static inline int i = 8; was suddenly implicitly inline, the definition above (that is in an existing code base) would be an odr-violation. Now previously well-formed code, is ill-formed. So it's best to allow only explicit inline to take effect here, since only new code will actually have it.


1 One could argue that static constexpr variables may have the same issue (and yet they are implicitly inline). But IIRC their original wording allowed this change without potentially breaking existing code. It was essentially already "inline" by everything but name.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • 2
    This answer would be better with an actual example of "problematic" behavior – Yakk - Adam Nevraumont Oct 22 '17 at 12:47
  • OP's code suggestion is already ill-formed, so the change would not break existing code. But it would be somewhat inconsistent – M.M Oct 22 '17 at 12:48
  • @M.M - OP's code is. But the same treatment would have to apply to **const** data members, which are well-formed. Any way, I'm in the process of expanding. Just a moment – StoryTeller - Unslander Monica Oct 22 '17 at 12:51
  • @Yakk - Better? I feel I may have faffed the note about `constexpr`. – StoryTeller - Unslander Monica Oct 22 '17 at 13:12
  • 2
    Only a bit better; the fact that `const int foo::n;` causes a ODR-violation due to lack of `inline` is not an essential part of the `inline` keyword but rather a choice of implementation of `inline` keyword here. So the *break* from assuming `inline` is now "because they chose it would be an ODR violation to use `inline` in the declaration, and later define it without `inline`", which just kicks the question down the road "why did they choose that is an ODR violation". I suspect due to analogy with `inline` functions? But is there *another* reason? – Yakk - Adam Nevraumont Oct 22 '17 at 23:30
  • `static constexpr` was made implicitly inline by making what had been the definition into a redundant redeclaration - see [depr.static_constexpr]. So...what's preventing the committee from doing the same thing here? – T.C. Oct 23 '17 at 23:01
  • @T.C. - And have the semantics of `static constexpr`, that are applicable for all types, be applicable with `static const`, but only on integral types? That seems more awkward than the way it is specified at this time. I can imagine the committee wanting to play it conservative. Besides, IMO we should be using `constexpr` for this anyway, and old code (that no longer needs older tool-chains) should be updated accordingly. But again, that's me, not the committee. – StoryTeller - Unslander Monica Oct 24 '17 at 05:34