模板显式特化之template<>语法

来源:互联网 发布:c语言双引号里面的数字 编辑:程序博客网 时间:2024/05/22 14:13
      最近在拜读侯捷老师的《STL源码剖析》,本着勤于实践的指导思想,使用gcc和vc分别编译运行了第27页的程序,此程序是用来测试SGI STL中的__STL_STATIC_TEMPLATE_MEMBER_BUG宏的。其代码如下:

#include<iostream>
using namespace std;


template<class T>
class testclass
{
public:
    static int _data;
};


int testclass<int>::_data = 1;
int testclass<char>::_data = 2;


int main()
{
    cout << testclass<int>::_data << endl;
    cout << testclass<char>::_data << endl;

    testclass<int> obji1, obji2;
    testclass<char> objc1, objc2;

    cout << obji1._data << endl;
    cout << obji2._data << endl;
    cout << objc1._data << endl;
    cout << objc2._data << endl;

    obji1._data = 3;
    objc2._data = 4;

    cout << obji1._data << endl;
    cout << obji2._data << endl;
    cout << objc1._data << endl;
    cout << objc2._data << endl;

    return 0;
}

    起初我使用的GCC是2.95.3-5(cygwin special)版本,一切如我所预料,编译运行顺利通过。然而,一时头脑发热,我想在较新版本上试试程序效果,使用MINGW32 gcc 4.5.4版本编译器——通过GNU官方资料来看,本版对C++ 03版本中规定的语言特性几乎全部支持。结果,在编译的时候,出现了如下错误提示:

D:\mingw32\bin>gcc c:\cygwin\home\config3.cpp -o c:\test.exe
c:\cygwin\home\config3.cpp:11:5: error: specializing member 'testclass<int>::_data' requires 'template<>' syntax
c:\cygwin\home\config3.cpp:12:5: error: specializing member 'testclass<char>::_data' requires 'template<>' syntax

    这是为什么呢?我又将代码放到VS2008和VC6环境下测试,顺利编译通过。看过上面的错误提示信息之后倒是提醒我,testclass<int>类似的写法表明我们针对testclass模板类进行了一次模板参数特化(explicit specialization)操作,按照c++教科书上面所说,模板特化操作语句前面需要加“template<>”修饰符。为了弄清楚真相,搬出C++标准文件(ISO/IEC 14882:2003)来,第14.7.3章节中明确的描述了模板特化语法为“template<>”形式前缀,以此告诉编译器这是一个模板特化行为。但是事情似乎总是存在例外,静态变量初始化操作中“template<>”形式语法在如下所述的情况中是不能够出现的,引用标准中原文如下:

A member of an explicitly specialized class is not implicitly instantiated from the member declaration of
the class template; instead, the member of the class template specialization shall itself be explicitly defined.
In this case, the definition of the class template explicit specialization shall be in scope at the point of decla-ration of the explicit specialization of the member.  The definition of an explicitly specialized class is unre-lated to the definition of a generated specialization.  That is, its members need not have the same names,
types, etc. as the members of the a generated specialization.  Definitions of members of an explicitly spe-cialized class are defined in the same manner as members of normal classes, and not using the explicit specialization syntax.  [Example:
template<class T> struct A {
    void f(T) { /* ... */ }
};
template<> struct A<int> {
    void f(int);
};
void h()
{
    A<int> a;
    a.f(16); // A<int>::f must be defined somewhere
}
//explicit specialization syntax not used for a member of
//explicitly specialized class template specialization
void A<int>::f() { /* ... */ }
—end example]

简洁点讲,上文是说在定义特化类中的成员函数或是静态成员变量初始化等操作的时候,不需要“template<>”前缀。为了检验此特性,将先前的代码稍作修改:

#include<iostream>
using namespace std;


template<class T>
class testclass
{
public:
    static int _data;
};


template<>
class testclass<int>
{
public:
    static int _data;
};


int testclass<int>::_data = 1;
template<> int testclass<char>::_data = 2;

int main()
{
    cout << testclass<int>::_data << endl;
    cout << testclass<char>::_data << endl;

    testclass<int> obji1, obji2;
    testclass<char> objc1, objc2;

    cout << obji1._data << endl;
    cout << obji2._data << endl;
    cout << objc1._data << endl;
    cout << objc2._data << endl;

    obji1._data = 3;
    objc2._data = 4;

    cout << obji1._data << endl;
    cout << obji2._data << endl;
    cout << objc1._data << endl;
    cout << objc2._data << endl;

    return 0;
}

    以上程序在gcc 2.95.3版本、gcc 4.5.4版本、VS2008和VC6下面编译测试通过。
    综上所述,MS系列的编译器对C++标准的支持程度应该还是逊色于gcc(作者个人观点)。

原创粉丝点击