extern i...">

Gcc variable spec template variable specification in gcc

// ih

template<int> extern int const i; 

//i.cpp

 #include "ih" template<> extern int constexpr i<0> = 42; 

//main.cpp

 #include "ih" int main() { return i<0>; } 

In C ++ 14/17 mode, this returns 42 using clang, but this is a bug with gcc: "Explicit template specification cannot have a storage class."

Is this a bug in gcc?

+5
source share
3 answers

There is a fairly simple solution to this problem. Please see this post in the ISO C ++ Standard - discussion forum and answer by Richard Smith for further details.

1. extern should not be specified in explicit specialization

So, to answer the original question: no, this is not an error in gcc , it is correct to report an error (as Massimiliano Yana answered).

Unlike clang, it really has a mistake here (as Massimiliano Jana already suggested), because extern accepted. Perhaps clang accepts this silently because it is the same as the primary template.

2. Theoretically (in accordance with the standard), the solution is to abandon extern , because the binding of templates by name and therefore specialization β€œinherits” the connection of the primary template (again see Massimiliano Jan's answer)

But in practice, it does not work, because both compilers are incorrect here, and explicit specialization incorrectly has an internal relationship instead of binding the primary template, which is external.

3. Briefly:

gcc never compiles, which is true in (1), but incorrect in (2). clang compiles in (1), which is incorrect but not compiled in (2), which is also not true.

I will write an error report for clang. If anyone is interested, write a gcc error. I will not do this because (unfortunately) I cannot use gcc in my Visual Studio development environment.

+2
source

The template of the primary variable must be declared extern, since it is a constant, and I do not want initializers in the header file (just like with the usual "extern int const i;"). Instead, I want specialization definitions in some kind of source file.

the solution should be to abandon the extern specialization.

because

[declarations / speciers-7.1.1] The storage class specifier should not be explicitly specified

the rationale is that all specializations must have the same relationship (see, for example, 605 defect report ). So this seems to be wrong.

In any case, given that compilers behave wildly on this, a workaround might be something like

 // ih template<int I> struct i_impl{ static const int value; }; template<int I> int const i = i_impl<I>::value; // i.cpp #include <ih> template<> const int i_impl<0>::value = 42; 
+1
source

According to N4340 :

A storage class specification other than thread_local should not be specified in explicit specialization (14.7.3) or explicit (14.7.2).

So this happens with the extern specifier. Just remove any storage specifier by specialization. In your code, remove the extern specifier. For instance:

 template<> int constexpr i<0> = 42; 
0
source

Source: https://habr.com/ru/post/1272638/


All Articles