为什么静态内联变量需要 "inline"?

Why is "inline" required on static inline variables?

C++17 允许这样定义静态成员变量:

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

要求 inline 规范背后的基本原理是什么?为什么不简单地让程序员写

    static int i = 8;

在 class?

没有inline,它被明确声明为只是一个声明。如 [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.

基本原理很可能是为了保持遗留代码的完整性和有效性。回想一下,我们可以在 class 定义本身中初始化整型常量。但是 odr-using 它们仍然需要在某些翻译单元中进行超出 class 的定义。

因此,使此类变量隐式内联在现有代码库中可能会出现问题。委员会一直在考虑添加核心语言功能时的向后兼容性。

例如,考虑这个有效的 C++03 class 定义:

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

n 可以用作常量表达式来定义 bar 的范围,并且它不被视为 odr-use。现在我们会把它写成 constexpr1,但是上面的仍然有效。但是 可能 情况下 n 必须使用 odr(想象它的地址被占用,或者引用绑定到它,等等)。它们可能不多,也可能不常见,但某些 API 有疯狂的要求,最终需要这个

const int foo::n;

出现在一些翻译单元中。

现在,如果 static inline int i = 8; 突然隐含地 inline,上面的定义(在现有代码库中)将是 odr 违规。现在以前格式正确的代码格式错误。所以这里最好只允许 explicit inline 生效,因为只有新代码才会真正有它。


1 有人可能会争辩说 static constexpr 变量可能有同样的问题(但它们是隐式内联的)。但是 IIRC 他们的原始措辞允许这种改变而不会破坏现有代码。除了名字之外,它基本上已经 "inline" 了。