10

我想知道为什么下面的代码在 gcc 中运行得很好

#include <iostream>
using namespace std;

template<typename T>
struct F { 
  static T const value;
};

template<> 
struct F<int> { // Specialization
    static int const value; 
}; 

template struct F<int>;

template<typename T>
T const F<T>::value = sizeof(T);

template<>
int const F<int>::value = 42;

int main() {

    struct F<int> ma;
    cout << ma.value;

    return 0;
}

http://ideone.com/wvrurz

在 MSVC 2012 上,我无法编译:

#include <iostream>
using namespace std;

template<typename T>
struct F {
  static T const value;
};

template<> 
struct F<int> { // Specialization
    static int const value; 
};

//template struct F<int>; // error C2950: 'F<int>' : cannot explicitly instantiate an explicit specialization

template<typename T>
T const F<T>::value = sizeof(T);

//template<>
//int const F<int>::value = 42; // error C2998: 'const int F<int>::value' : cannot be a template definition

int main() {

    struct F<int> ma;
    cout << ma.value;

    return 0;
}

从我在 n3242 §14.7 5 中读到的内容

显式实例化和显式特化的声明都不应出现在程序中,除非显式实例化遵循显式特化的声明。

我相信情况就是这样。我错过了什么吗?

4

1 回答 1

9

太长; 没读

  • msvc 2012正确拒绝标记的行// error C2998

  • 然而,前一个诊断是错误的,应该被接受;就像在较新版本的编译器中一样。

注意:可以在此处找到与 C2950 相关的错误报告。


关于C2950

msvc 2012对有问题的线路发出诊断是错误的。

template<class T> struct A;

template<>
struct A<int> { };

template struct A<int>; // legal

int main () { }

该标准规定显式实例化应该包含一个simple-template-id,这正是它的本质A<int>,并且说的是;它是合法的 C++

14.6.2p3 显式实例化 [temp.explicit]

如果显式实例化用于类或成员类,则声明中的详细类型说明符应包括一个simple-template-id

14.2p1 模板特化的名称 [temp.names]

模板特化 (14.7) 可以由template-id引用:

simple-template-id:
         template-name < template-argument-list_opt >


措辞变化: C++03 vs C++11

14.7.2p5有一些从C++11开始的新措辞,这些措辞是在以下缺陷报告之后实施的:

14.7.2p5 显式实例化 [temp.explicit]

对于给定的一组模板参数,如果模板的显式实例化出现在该模板的显式特化声明之后,则显式实例化无效。

注意感谢@dyp引起对先前链接的DR的关注。


关于C2998

这个错误是准确的;您不是指依赖于模板参数的东西,这意味着您不应该template<>在有问题的定义上使用。

较新版本的gcc问题对此进行了诊断,并且clang正确地拒绝了这样的定义。

template<class T> struct A;

template<>
struct A<int> { 
  static int const value;
};

template<> int const A<int>::value = 42; // ill-formed, `value` does not depend on
                                         //              any template parameter since it's
                                         //              explicitly a part of `A<int>`

int main () { }
gcc   => foo.cpp:8:22: warning: too many template headers for A<int>::value (should be 0)
clang => foo.cpp:8:1: error: extraneous 'template<>' in declaration of variable 'value'
msvc  => foo.cpp(8) : error C2998: 'const int A<int>::value' : cannot be a template definition

上述诊断正确。


有问题的行违反了标准的以下部分:

14.7.3p5 明确的专业化 [temp.expl.spec]

显式特化类模板的成员以与普通类成员相同的方式定义,并且不使用template<>语法。定义显式特化成员类的成员时也是如此。

于 2014-06-20T20:30:15.240 回答