C++ 标准:namespace-scoped constexpr 变量是否具有内部链接?
C++ standard: do namespace-scoped constexpr variables have internal linkage?
假设我们有一个 header 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说
A name having namespace scope has internal linkage if it is the name of [...] a non-inline variable of non-volatile const-qualified type that is neither explicitly declared extern nor previously declared to have external linkage [...]
但是不知道constexpr
算不算"const-qualified"。标准在某处这么说吗?
假设这保证有内部链接,那么这种用法的ODR似乎没有问题,对吗? (与 中的内容相反。)
是的,对象声明上的 constexpr
表示该对象是 const
。参见 [dcl.constexpr]/9。是的,这意味着您示例中的 kSomeString
具有内部链接。
我们这里说的ODR违规种类并不是kSomeString
的定义本身,而是其他试图利用它的定义。恰恰是因为内部链接存在问题。考虑:
void f(const std::string_view &);
inline void g() {
f(foo::kSomeString);
}
如果包含在多个翻译单元中,这将违反 ODR,主要是因为每个翻译单元中 g
的定义引用了不同的对象。
您对 kSomeString
的用法完全有效。
要事第一;您的对象是 const 限定的,如 T.C。解释。进一步就是literal type,因为它有一个constexpr构造函数。因此,如果您在头文件中定义的函数中使用它,则适用标准中的以下例外情况(第 3.2 章):
There can be more than one definition of an inline function with
external linkage (7.1.2), non-static function template (14.5.6), (…)
in a program provided that each definition appears in a different
translation unit, and provided the definitions satisfy the following
requirements. Given such an entity named D defined in more than one
translation unit, then
- each definition of D shall consist of the same sequence of tokens; and
- in each definition of D, corresponding names, looked up according to 3.4, shall refer to an entity defined within the definition of D,
or shall refer to the same entity, after overload resolution (13.3)
and after matching of partial template specialization (14.8.3),
except that a name can refer to a const object with internal or no
linkage if the object has the same literal type in all definitions of
D, and the object is initialized with a constant expression (5.19),
and the value (but not the address) of the object is used, and the
object has the same value in all definitions of D;
- (…)
假设我们有一个 header 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说
A name having namespace scope has internal linkage if it is the name of [...] a non-inline variable of non-volatile const-qualified type that is neither explicitly declared extern nor previously declared to have external linkage [...]
但是不知道constexpr
算不算"const-qualified"。标准在某处这么说吗?
假设这保证有内部链接,那么这种用法的ODR似乎没有问题,对吗? (与
是的,对象声明上的 constexpr
表示该对象是 const
。参见 [dcl.constexpr]/9。是的,这意味着您示例中的 kSomeString
具有内部链接。
我们这里说的ODR违规种类并不是kSomeString
的定义本身,而是其他试图利用它的定义。恰恰是因为内部链接存在问题。考虑:
void f(const std::string_view &);
inline void g() {
f(foo::kSomeString);
}
如果包含在多个翻译单元中,这将违反 ODR,主要是因为每个翻译单元中 g
的定义引用了不同的对象。
您对 kSomeString
的用法完全有效。
要事第一;您的对象是 const 限定的,如 T.C。解释。进一步就是literal type,因为它有一个constexpr构造函数。因此,如果您在头文件中定义的函数中使用它,则适用标准中的以下例外情况(第 3.2 章):
There can be more than one definition of an inline function with external linkage (7.1.2), non-static function template (14.5.6), (…) in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. Given such an entity named D defined in more than one translation unit, then
- each definition of D shall consist of the same sequence of tokens; and
- in each definition of D, corresponding names, looked up according to 3.4, shall refer to an entity defined within the definition of D, or shall refer to the same entity, after overload resolution (13.3) and after matching of partial template specialization (14.8.3), except that a name can refer to a const object with internal or no linkage if the object has the same literal type in all definitions of D, and the object is initialized with a constant expression (5.19), and the value (but not the address) of the object is used, and the object has the same value in all definitions of D;
- (…)