为什么静态内联变量需要 "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。现在我们会把它写成 constexpr
1,但是上面的仍然有效。但是 可能 情况下 n
必须使用 odr(想象它的地址被占用,或者引用绑定到它,等等)。它们可能不多,也可能不常见,但某些 API 有疯狂的要求,最终需要这个
const int foo::n;
出现在一些翻译单元中。
现在,如果 static inline int i = 8;
突然隐含地 inline
,上面的定义(在现有代码库中)将是 odr 违规。现在以前格式正确的代码格式错误。所以这里最好只允许 explicit inline
生效,因为只有新代码才会真正有它。
1 有人可能会争辩说 static constexpr
变量可能有同样的问题(但它们是隐式内联的)。但是 IIRC 他们的原始措辞允许这种改变而不会破坏现有代码。除了名字之外,它基本上已经 "inline" 了。
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。现在我们会把它写成 constexpr
1,但是上面的仍然有效。但是 可能 情况下 n
必须使用 odr(想象它的地址被占用,或者引用绑定到它,等等)。它们可能不多,也可能不常见,但某些 API 有疯狂的要求,最终需要这个
const int foo::n;
出现在一些翻译单元中。
现在,如果 static inline int i = 8;
突然隐含地 inline
,上面的定义(在现有代码库中)将是 odr 违规。现在以前格式正确的代码格式错误。所以这里最好只允许 explicit inline
生效,因为只有新代码才会真正有它。
1 有人可能会争辩说 static constexpr
变量可能有同样的问题(但它们是隐式内联的)。但是 IIRC 他们的原始措辞允许这种改变而不会破坏现有代码。除了名字之外,它基本上已经 "inline" 了。