Global variables and constexpr (inline or not?)
Asked Answered
S

1

0

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?

Syllable answered 31/12, 2020 at 12:39 Comment(0)
H
1

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.

Hobgoblin answered 31/12, 2020 at 13:20 Comment(2)
Ok, so this is only for template variables, strange. I was using g++-10 and it gave me no error as you said. I will declare them inline. Thanks.Syllable
@Syllable It should fail with Clang (after you fix a compilation error due to uninitialized num<T>).Hobgoblin

© 2022 - 2024 — McMap. All rights reserved.