我有一个关于 constexpr 定义在类定义中声明为 const (且未指定内联或 constexpr)的文字类型静态数据成员的问题:
// S.h
struct S
{
static int const i; // not specified inline or constexpr
};
// S.cpp
#include "S.h"
constexpr int const S::i = 42; // definition, not declaration
//主.cpp
#include "S.h"
int main()
{
return S::i;
}
Clang/gcc 在 C++11/14 模式下返回 42,但在 C++17 模式下报告错误(对 S::i 的未定义引用)。如果我注释掉 constexpr,它们也会在 C++17 模式下返回 42。
S::i 具有外部链接,因为 S 具有外部链接。 S::i 未声明为 constexpr,因此(如果我没有记错的话)C++17 10.1.5 p1 不适用:
使用 constexpr 声明的函数或静态数据成员
说明符隐式是内联函数或变量
我理解这句话的意思好像是(加粗我的理解):
使用 constexpr 说明符声明的静态数据成员在类定义中隐式是一个内联变量
因此 S::i 不是内联变量。
然而 S::i 的定义似乎在 C++17 模式下具有内部链接,就好像 constexpr 意味着内联一样。它是否正确?如果是这样,标准中的证据在哪里?
还是我误解了 10.1.5 p1 它的真正含义(粗体显示我的误解):
使用 constexpr 说明符声明的静态数据成员在类定义和命名空间范围内的定义是隐式的内联变量吗?
[dcl.内联]/6 states:
如果具有外部链接的函数或变量被声明为内联
一个翻译单元,应在所有翻译中声明为内联
它出现的单位;无需诊断。
所以正如你所指出的,if我们可以证明constexpr
隐含地暗示inline
,它将解释您的示例的未定义引用错误。
[dcl.constexpr]/1国家[强调我的]:
应应用 constexpr 说明符只针对定义的
变量或变量模板或函数的声明或
函数模板。
也:
使用 constexpr 说明符声明的函数或静态数据成员
隐式是一个内联函数或变量([dcl.内联]).
[基本.def]/1国家[强调我的]:
声明可以将一个或多个名称引入翻译单元或重新声明先前声明引入的名称.
以及 (/2):
声明是定义,除非:
[...没有一个适用于constexpr int const S::i = 42;
]
这里的本质是定义是声明(完全定义了声明引入的实体),所以constexpr int const S::i = 42;
(除了作为定义之外)也是一个(重新)声明,在这种情况下 [dcl.constexpr]/1 适用,并且S::i
内联在翻译单元中S.cpp
,因此,由 [dcl.inline]/6,在它出现的所有其他翻译单元中。相反,通过 [dcl.constexpr]/1,constexpr
说明符,例如特别是在静态数据成员的上下文中,只能出现在定义的声明中。
与后者的情况有些相关的是,constexpr
从 C++17 开始,带初始化的静态数据成员声明也是一个定义,允许以下规范:constexpr
只能应用于变量定义(即,永远不会应用于非初始化声明)。看[depr.static_constexpr]/1.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)