Imagine we have a header foo.h
containing the following:
#ifndef FOO_H_
#define FOO_H_
namespace foo {
constexpr std::string_view kSomeString = "blah";
}
#endif // FOO_H_
Is foo::kSomeString
guaranteed to have internal linkage in any translation unit that includes foo.h
? Does this vary between C++11 and C++17?
In the draft standard [basic.link]/3 says
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 [...]
But I don't know if constexpr
counts as "const-qualified". Does the standard say so somewhere?
Assuming this is guaranteed to have internal linkage, it seems like there can be no problem with the ODR for this usage, right? (In contrast to what it says in this answer.)
Const and constexpr global variables have internal linkage by default (and thus don't need the static keyword -- if it is used, it will be ignored).
A constexpr specifier used in an object declaration or non-static member function (until C++14) implies const . A constexpr specifier used in a function or static data member (since C++17) declaration implies inline .
Yes, constexpr
on an object declaration means that the object is const
. See [dcl.constexpr]/9. And yes, that means that kSomeString
in your example has internal linkage.
The species of ODR violation we are talking about here is not the definition of kSomeString
itself, but other definitions that attempt to use it. And there's a problem precisely because of the internal linkage. Consider:
void f(const std::string_view &);
inline void g() {
f(foo::kSomeString);
}
This is an ODR violation if included in multiple translation units, essentially because the definition of g
in each translation unit references a different object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With