Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is "inline" required on static inline variables?

Tags:

c++

c++17

inline

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?

like image 863
oz1cz Avatar asked Oct 22 '17 12:10

oz1cz


People also ask

What is the use of static inline?

Static inline functions are simple. Either a function defined with the inline function specifier is inlined at a reference, or a call is made to the actual function. The compiler can choose which to do at each reference. The compiler decides if it is profitable to inline at -xO3 and above.

What is inline static variable?

The inline variable is allowed to be defined in multiple translation units. It also follows the one definition rule. If this is defined more than one time, the compiler merges them all into a single object in final program.

Is the inline keyword required to inline a class method?

Yes, but it's less relevant - for a function to be inlined, it's body must be in the same compilation unit (for instance, in a header). That's less common in C programs. defining a non-member function template (aka non-static function template) does not require inline.

Can static member function inline?

That said, the function being static will not prevent it from being inlined; static functions are basically free functions with a different naming style and access to the class' private members.


1 Answers

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.

like image 100
StoryTeller - Unslander Monica Avatar answered Oct 30 '22 21:10

StoryTeller - Unslander Monica