模板类静态成员变量在使用'extern template class'语法时的特殊化

Specialization of a template class static member variable when also using 'extern template class' syntax

本文关键字:class template 语法 特殊化 extern 变量 静态成员      更新时间:2023-10-16

我有一个模板类,我只打算将它与我提前知道的3种不同类型一起使用。为了减少代码膨胀,我希望尽可能多地保留在标头之外。模板类还具有静态变量,这些变量必须根据专业化而有所不同。

我尝试在使用Visual C++19.15.26729的Windows和使用XCode和clang-900.0.39.2的Mac上实现这一点。我需要不同的代码来满足每个编译器,更糟糕的是,编译器抱怨对方的程序版本"好"。

这里有一个最小的例子:

// A.h
template<typename T>
class A
{
public:
static T x;
};
// template<> int A<int>::x; // PROBLEMATIC PART
extern template class A<int>;
// A.cpp
#include "A.h"
template<> int A<int>::x = 42;
template class A<int>;
// main.cpp
#include "A.h"
int main()
{
return A<int>::x;
}

上面的代码(注释行)在VC++上编译得很好,但clang抱怨道:Explicit specialization of 'x' after instantiation

这个问题的答案很有帮助:What';当使用";外部模板";?

在未注释template<> int A<int>::x;的情况下,它在Xcode上编译得很好,但随后Visual C++抱怨道:

1>A.cpp(3): error C2086: 'T A<int>::x': redefinition
1>        with
1>        [
1>            T=int
1>        ]
1>A.h(9): note: see declaration of 'x'
1>A.cpp(3): error C2086: 'T A<T>::x': redefinition
1>        with
1>        [
1>            T=int
1>        ]
1>A.h(6): note: see declaration of 'A<int>::x'

我的做法根本错误吗?这是编译器错误吗?也许这是一个只有一个编译器支持的功能,如果是这样的话——根据标准,哪个版本是正确的?

这确实是Microsoft编译器中的一个错误,已经记录在他们的积压工作中。关注此问题以获取更新:https://developercommunity.visualstudio.com/content/problem/319447/explicit-specialization-of-static-data-member-inco.html

MSVC在这里是错误的:"有问题的"行不是定义,因为它没有初始值设定项。

同时,Clang拒绝没有该声明的版本是正确的,因为显式实例化声明也是A<int>::x的显式实例化宣言。