c++language-lawyerexternvariable-templates

storage class for variables template at global/named namespace scope


While trying to get my thoughts straight about storage class, I wrote the following snippet:

#include <iostream>

template<typename T> T pi;
template<> extern int pi<int>;

int main() {
    std::cout << pi<int> << '\n';
}

LIVE

gcc gives me a compilation error explicit template specialization cannot have a storage class that I can't relate with, for instance, cppreference storage class specifiers.

clang compiles but gives me a "undefined reference" error on link which disappear if I initialize the variable with: template<> extern int pi<int>{3};
But it gives me a warning about initializing an extern variable (which would be, if I get it right, a plain error with a non-template variable)

msvc compiles and links without blinking an eye.

Which compiler is correct (if any) and why?

NB in real code I would have made the specialization inline constexpr


Solution

  • GCC's diagnostic is correct, as per [temp.expl.spec]/2:

    An explicit specialization shall not use a storage-class-specifier other than thread_local.