还使用“外部模板类”语法时,模板类静态成员变量的特化

时间:2019-02-01 16:08:20

标签: c++ templates visual-c++ clang template-specialization

我有一个模板类,我只打算与提前知道的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's the right way to specialize a template when using "extern template"?

取消注释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'

我的方法根本上是错误的吗?它是编译器错误吗?也许只有一个编译器支持此功能-如果符合标准,哪个版本正确?

2 个答案:

答案 0 :(得分:0)

MSVC是错在这里:在“有问题”行是不是定义,因为它has no initializer

锵是同时正确拒绝版本,而无需该声明因为显式实例声明为also an explicit instantiation declaration of A<int>::x

答案 1 :(得分:0)

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