想象一下,我们有一个标题foo.h
,其中包含以下内容:
#ifndef FOO_H_
#define FOO_H_
namespace foo {
constexpr std::string_view kSomeString = "blah";
}
#endif // FOO_H_
foo::kSomeString
是否保证在包含foo.h
的任何翻译单元中都有内部链接?这在C ++ 11和C ++ 17之间是否有所不同?
标准草案[basic.link]/3中说
具有命名空间作用域的名称具有内部链接,如果它是非易失性const限定类型的非内联变量的名称,该变量既未显式声明为extern,也未声明为具有外部链接[。 ..]
但我不知道constexpr
是否算作" const-qualified"。标准是否在某处说出来?
假设这保证有内部链接,看起来这种用法的ODR没有问题,对吧? (与this answer中的内容相反。)
答案 0 :(得分:17)
是,对象声明上的constexpr
表示对象为const
。见[dcl.constexpr]/9。是的,这意味着您的示例中的kSomeString
具有内部链接。
我们在这里讨论的ODR违规种类不是kSomeString
本身的定义,而是其他尝试使用它的定义。正是由于内部联系,存在一个问题。考虑:
void f(const std::string_view &);
inline void g() {
f(foo::kSomeString);
}
如果包含在多个翻译单元中,这是ODR违规,主要是因为每个翻译单元中g
的定义引用了不同的对象。
答案 1 :(得分:-1)
您对await
的使用完全正确。
第一件事首先;您的对象具有const资格,即T.C。解释。此外,literal type的原因在于它具有constexpr构造函数。因此,如果在头文件中定义的函数中使用它,则该标准中的以下例外适用(第3.2章):
内联函数可以有多个定义,其中 外部链接(7.1.2),非静态功能模板(14.5.6),(…) 在程序中,前提是每个定义都以不同的方式出现 翻译单元,并提供满足以下条件的定义 要求。给定这样一个名为D的实体,它在多个 翻译单元,然后
- D的每个定义应包含相同的令牌序列;和
- 在D的每个定义中,按照3.4查找的相应名称应指代D定义中定义的实体, 或应在重载解决方案(13.3)之后引用同一实体 在匹配了部分模板专业化(14.8.3)之后, 除了名称可以引用具有内部或不具有内部名称的const对象外 如果对象的所有定义中具有相同的文字类型,则链接 D,然后使用常量表达式(5.19)初始化对象, 然后使用对象的值(而不是地址),并且 对象在D的所有定义中具有相同的值;
- (...)