C ++标准:命名空间范围的constexpr变量是否具有内部链接?

时间:2017-09-08 01:29:19

标签: c++ c++11 language-lawyer c++17 linkage

想象一下,我们有一个标题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中的内容相反。)

2 个答案:

答案 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的所有定义中具有相同的值;
  •   
  • (...)
  •