• C++泛型设计 - 模板规格(译)

    2007-03-26

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://dreamerate.blogbus.com/logs/4859338.html

    C++泛型设计 - 模板规格(译)

     

    C++关键字template可以用来声明一批参数化的类(模板类)或函数(模板函数)。

     

    一般使用格式如下:

     

    template < template-parameter-list > declaration

     

    说明

           template-parameter-list是一个以逗号分隔开的模板参数。这些模板参数可能是一些类型(以这种格式:class identifiertypename identifier或是template class identifier)或是一些非类型的参数,它们常用于模板体内,代表着实际使用时指定的类型或是非类型的对象。模板参数的语法如下之一:

     

    parameter-declaration

    ²        class identifier [ = typename ]

    ²        typename identifier [ = typename ]

    ²        template < template-parameter-list > class [identifier][= name]

     

    你可以像实例化一个普通类一样去实例化一个类模板多次,但你必须以一对尖括号(<>)来包含模板参数。这些模板参数可以是任意类型(template-parameter-list包含class或是typename关键字)或是一个适当类型的值(template-parameter-list包含非类型的参数)。调用一个模板函数没有特定的语法,尽管尖括号和模板参数是必需的(当模板参数不能由参数到函数引出时)。

     

    如下所示,template-parameter-list的几个部分都是不同的,这些参数主要用于在模板类中的函数。

     

    template< class T, int i > class MyStack...

     

    在这个例子中,这个模板可以接爱一个类型(class T)和一个常量参数(int i)。上面这个例子的模板将使用类型T和常量的整数i。在MyStack声明的类体中,你必须引用到这个标识符T

     

    一个模板的声明不会产生代码,它仅阐释一个类或函数的组织,当它被其它代码引用时才会产生。

     

    模板可以在全局或是名字空间及类域下进行声明,但不能在一个函数内声明。

     

    下面这个例子演示了一个类模板以一个类型T及一个非类型模板参数i进行的声明、定义及实例化:

     

    实例

     

    ////////////////////////////////////////////////////////////////////////////////////////////////

    // template_specifications1.cpp

     

    // Template Class Usage 1: The T is Type, and the i is constant value of Integer

    template <class T, int i>

    class TestClass

    {

        public:

            char buffer[i];

            T testFunc(  T* p1 );

    };

     

    template <class T, int i>

    T TestClass::testFunc(T* p1)

    {

        return *(p1++);

    }

     

    // To create an instance of TestClass

    TestClass<char, 5> ClassInst;

    int main()

    {}

     

    ////////////////////////////////////////////////////////////////////////////////////////////////

    // template_specifications2.cpp

    class Y

    {};

     

    // Template Class Usage 2: The pT is Value of Pointer

    template <class T, T* pT>

    class X1

    {};

     

    // Template Class Usage 3: The T2 is optional Default Parameter

    template <class T1, class T2 = T1>

    class X2

    {};

     

    // To create those instances of upon classes

    Y aY;

    X1 x1;

    X2<int> x2;

     

    int main()

    {}

     

    ////////////////////////////////////////////////////////////////////////////////////////////////

    // template_specifications3.cpp

    #include

     

    // Template Structure Usage 1Normal

    template <class T>

    struct str1

    {

        T t;

    };

     

    // Template Structure Usage 2The Type of T can be a template class

    template <template<class A> class T>

    struct str2

    {

        T<int> t;

    };

     

    int main()

    {

        str2 mystr2;

        mystr2.t.t = 5;

        printf_s( “%d\n”, mystr2.t.t );

    }

     

    /* ---------------------- */

    输出

    5

    ////////////////////////////////////////////////////////////////////////////////////////////////

    // references__supported_as_nontype_template_parameters.cpp

    #include

     

    extern “C” int printf( const char*, ... );

     

    template <int& ri>

    struct S

    {

        // constructor method

        S()

        {

    printf( “ ri is %d\n”,  ri  );

    }

       

        // destructor method

        ~S()

        {

            printf( “ri is %d\n”, ri );

    }

    };

     

    int i = 1;

    int main()

    {

        S s;

        i = 0;

    }

     

    /* ---------------------- */

    输出

    ri is 1

    ri is 0

    ////////////////////////////////////////////////////////////////////////////////////////////////

     

    非类型的模板参数

     

    非类型的模板参数必须是:整数/枚举/指针/引用/指向一个成员类型的指针(例如template_specifications2.cppX1模板类)。正如constvolatile类型一样,在编译时刻它们是不可改变的。另外,float类型的指针不能用作模板参数。尽管一个指向 “类对象/结构/union类型”的指针可用作模板参数,但是它们本身却不可用作模板参数。若传递的是数组名称,就被转化为指针看待。若传递的是函数名称,当然,是被看作为函数指针。字符串是不允许看作为模板参数的。

     

    在一个模板声明中使用typename

     

    在模板参数列表中,可以使用typename关键字来定义一个参数。例如下面的模板声明是一样的:

     

    template class X...

    template class X...

     

    缺省的模板参数

     

    类模板可以拥有缺省参数(指定使用赋值操作符赋一个缺省的类型或是一个值)。确记,函数模板不可有缺省参数。

     

    ////////////////////////////////////////////////////////////////////////////////////////////////

    /* 类模板缺省参数用法参考简单例子 */

     

    template<typename Type>

    class allocator

    {};

     

    template<typename Type, typename Allocator = allocator>

    class stack

    {};

     

    stack<int> MyStack;

    ////////////////////////////////////////////////////////////////////////////////////////////////

     

    模板参数的复用

     

    在模板参数列表中,模板参数可以复用。如template_specifications2.cpp例子中的X1模板类的模板参数T在第二个参数中获得到复用。

     

    模板的模板参数

     

    模板参数也可以进行模板化。这个创立前提条件是,参数本身必须是一个模板,非一个由模板构造好的类。在下面的例子中,模板参数的名称A对于一个模板的模板参数来说,可以省略,因为没有被使用。

     

    引用模板参数

    Visual Studio .NET 2003引入了一个新特性,可以引用非类型的模板参数。这个方法在以前的版本中是不允许的。

     

    —完


    收藏到:Del.icio.us