Constexpr string literals in anonymous namespace?

I have the following code example that uses a string literal as a template parameter so that the base class template can access the string.

The code compiles, but I get a warning that I don't quite understand:

warning: 'ns :: bar :: type has a base' ns :: base <((const char *) (& ns :: bar :: name))> whose type uses an anonymous namespace [enabled by default]

An example of a working example below:

// "test.h" #pragma once namespace ns { template <char const* str> struct base { const char *name() const { return str; } }; namespace bar { static constexpr char name[] = "bar"; struct type : base<name> {}; // <-- this line here } } // main.cpp #include <iostream> #include "test.h" int main() { ns::bar::type f; std::cout << f.name() << std::endl; return 0; } 

So my questions are:

  • What does this warning mean?
  • Is it possible to pass a string literal as a template parameter in the way that I am doing here?

(Note that this is with gcc 4.7.2)

+6
source share
2 answers

The problem is that static constexpr char name[] = "bar"; has an internal binding.

Any internally linked type defined in the header will have a different type in each file that includes the header.

This rare intention is therefore a warning.

The reason that there is no warning in the source file is because this type cannot be referenced by more than one file, so it will always be one type.

+7
source

The warning is that name will have a different address in each source file that includes test.h Since it has an internal connection ( static ), each translation unit will receive its own copy; it will not be merged by the linker. This means that your code is equivalent:

 template<int> struct base { ... }; static constexpr int val = some_value_different_in_every_source_file; struct type: base<val> {}; 

Your code is legal as presented, but if you include test.h in another source file, it breaks the rule with one definition:

3.2 One definition rule [basic.def.odr]

[...]
6 - There may be more than one class type definition [...] provided [...]: [...]

  • in each definition of D , the corresponding names [...] can refer to a const object with internal or no binding [only] if the value (but not the address) of the object [...] is used [...]

You use the address of the object with internal binding in the definition of the class type, so its use in several translation units is undefined behavior.

+3
source

All Articles