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

问题描述 投票:15回答:2

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

c++ c++11 language-lawyer c++17 linkage
2个回答
17
投票

是的,constexpr对象声明意味着对象是const。见[dcl.constexpr]/9。是的,这意味着你的例子中的kSomeString有内部联系。

我们在这里讨论的ODR违规物种不是kSomeString本身的定义,而是其他试图使用它的定义。正是由于内部联系,存在一个问题。考虑:

void f(const std::string_view &);

inline void g() { 
    f(foo::kSomeString); 
}

如果包含在多个翻译单元中,这是ODR违规,主要是因为每个翻译单元中g的定义引用了不同的对象。


-1
投票

您对kSomeString的使用是完全有效的。

首先要做的事情;你的对象是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),除了如果对象在D的所有定义中具有相同的文字类型,并且该对象用常量表达式(5.19)初始化,并且值(但不使用对象的地址),并且对象在D的所有定义中具有相同的值;
  • (…)
© www.soinside.com 2019 - 2024. All rights reserved.