How does template affect linkage of const global variable?

263 Views Asked by At

As the doc says (emphasis mine):

Any of the following names declared at namespace scope have internal linkage:

  • non-volatile non-template non-inline const-qualified variables (including constexpr) that aren't declared extern and aren't previously declared to have external linkage;

So I'd expect const template variables to have external linkage. So I did a test:

// main.cpp
void other();

template<class T> T var = 1;
template<class T> const T constVar = 1;

int main() {
  std::cout << var<int> << ' ' << constVar<int> << std::endl;
  other();
}

// other.cpp
template<class T> T var = 2;
template<class T> const T constVar = 2;

void other() {
  std::cout << var<int> << ' ' << constVar<int> << std::endl;
}

And the output is:

1 1
1 2

The second column is for constVar, and it differs for different rows (printed from different translation units). This makes me think that it actually has internal linkage, despite being a template.

I understand that I do violate ODR, but only to understand what's happening.

So does constVar actually have internal linkage? If yes, what does the highlighted fragment of the doc mean? If no, then what's happening, and why do we need this highlighted fragment?

1

There are 1 best solutions below

2
On

C++14 N4296 §14.4

A template name has linkage (3.5). [...] Template definitions shall obey the one definition rule (3.2).

C++14 N4296 §3.2.6

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; [...]

If D is a template and is defined in more than one translation unit, then the preceding requirements shall apply both to names from the template’s enclosing scope used in the template definition (14.6.3), and also to dependent names at the point of instantiation (14.6.2). If the definitions of D satisfy all these requirements, then the behavior is as if there were a single definition of D. If the definitions of D do not satisfy these requirements, then the behavior is undefined.

Templates are implicitly inline i.e. have external linkage. What's happening = undefined behaviour. Compiler is not required to diagnose your code and might produce unexpected/inconsistent results.