lucmobz
lucmobz

Reputation: 483

Global variables and constexpr (inline or not?)

If I have: a.hpp a.cpp and main.cpp includes a.hpp, and in a.hpp I write

template<typename T>
constexpr int num;
template<>
constexpr int num<float> = 1;
template<>
constexpr int num<double> = 2;

Do I risk defining the variable num multiple times both in a.o and main.o? Or is it declared inline? Shall I put template variables specializations inside a.cpp? What changes if I wrap a.hpp into a namespace?

Upvotes: 0

Views: 464

Answers (1)

Evg
Evg

Reputation: 26342

Do I risk defining the variable num multiple times both in a.o and main.o?

You do. For non-template variables, constexpr implies const and const at the namespace level implies internal linkage, but not for variable templates. It seems that this is underspecified in the standard. The current draft has the following

Note 1: An instantiated variable template that has const-qualified type can have external or module linkage, even if not declared extern.

Experimentally, different compilers give them different linkages. For example, with GCC 9.3.0 and 10.2.0 num<float> has internal linkage:

nm -C a.o
...
0000000000000004 r num<float>

but with Clang 10.0.0 it has external linkage:

nm -C a.o
...
0000000000000000 R num<float>

As a result, if you try to include a.hpp in two compilation units, you'll get a link error with Clang.


Or is it declared inline?

No, explicit inline is needed.

What changes if I wrap a.hpp into a namespace?

I guess you're talking about an unnamed namespace. In this case each compilation unit is guaranteed to get its own (private) copy.

Upvotes: 1

Related Questions