4

If I have a header foo.h which contains

#ifndef FOO_H_
#define FOO_H_

namespace foo {
constexpr std::string_view kSomeString = "blah";
}

#endif  // FOO_H_

then is it safe to include foo.h from within multiple .cc files in a single program, regardless of what they do with the symbol kSomeString, or are there some uses that could cause an ODR violation?

Also, is it guaranteed that kSomeString.data() will return the same pointer across .cc files?

I'd like specific references to wording in the C++ standard if possible. Thanks!

jacobsa
  • 5,719
  • 1
  • 28
  • 60
  • 3
    What exactly does this have to do with `string_view` specifically? – Nicol Bolas Aug 14 '17 at 00:37
  • 1
    Most of the question is about `constexpr` declarations in headers generally, but there may be special issues around the use of a C string for initialization that don't apply to e.g. `constexpr int`. – jacobsa Aug 14 '17 at 00:41

1 Answers1

8

Merely including foo.h from multiple translation units will not violate the ODR. However, indeed, there are some uses of kSomeString that will violate the ODR. See here for details and standard wording: https://stackoverflow.com/a/34446445

It is not guaranteed that kSomeString.data() will return the same value in all translation units because it is not guaranteed that the string literal "blah" is the same object in all translation units. According to [lex.string]/16,

Evaluating a string-literal results in a string literal object with static storage duration, initialized from the given characters as specified above. Whether all string literals are distinct (that is, are stored in nonoverlapping objects) and whether successive evaluations of a string-literal yield the same or a different object is unspecified. [ Note: The effect of attempting to modify a string literal is undefined. — end note ]

In C++17, the potential ODR violations can be prevented by defining kSomeString to be inline. This will give it external linkage and hence a single address throughout the program (see [basic.link]/3 and [basic.link]/4) and allow it to be multiply defined (see [basic.def.odr]/4). Obviously .data() can then only return one possible value.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312
  • Are you sure that there are some ODR-problematic uses of `kSomeString` in my example? It seems like [basic.link/3.2](http://eel.is/c++draft/basic.link#3.2) guarantees that it will have internal linkage in all translation units, since it is namespace scoped and const. – jacobsa Sep 06 '17 at 23:29
  • (To answer my own question: see [this answer](https://stackoverflow.com/a/46107877/1505451), which gives an example of a problematic use.) – jacobsa Sep 08 '17 at 03:03