22

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.)

2
  • 1
    Yes, constexpr on declarations implies const in C++11. In C++14 and above, it only implies const on variables, not on member functions. Commented Sep 8, 2017 at 1:45
  • Thanks! Do you know which section of the standard says that? Commented Sep 8, 2017 at 2:08

2 Answers 2

22

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you! Your example of ODR issues makes sense—g is not the same in each translation unit. Is it possible to have problems that don't involve inline functions?
@jacobsa : templates taking non-type parameters are the other obvious example.
@T.C., I'm afraid I'm not quite with you on this one, please take a look at my answer.
0

Your usage of kSomeString is perfectly valid.

First things first; your object is const-qualified, as T.C. explained. Further is it of literal type, because it has a constexpr constructor. Therefore if you use it in a function defined in a header file, the following exception in the standard applies (chapter 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;
  • (…)

2 Comments

"and the value (but not the address) of the object is used". Binding a reference uses its address.
@T.C. You are right, but I am not wrong :). I haven't encouraged taking its address. I agree your particular use is a pitfall, but wanted to point out, that using such object in the shared definition is not wrong generally.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.