C++ template

1. 模板的概念。

我们已经学过重载(Overloading),对重载函数而言,C++的检查机制能通过函数参数的不同及所属类的不同。正确的调用重载函数。例如,为求两个数的最大值,我们定义MAX()函数需要对不同的数据类型分别定义不同重载(Overload)版本。

//函数1.

int max(int x,int y);
{return(x>y)?x:y ;}

//函数2.
float max( float x,float y){
return (x>y)? x:y ;}

//函数3.
double max(double x,double y)
{return (c>y)? x:y ;}

但如果在主函数中,我们分别定义了 char a,b; 那么在执行max(a,b);时 程序就会出错,因为我们没有定义char类型的重载版本。

现在,我们再重新审视上述的max()函数,它们都具有同样的功能,即求两个数的最大值,能否只写一套代码解决这个问题呢?这样就会避免因重载函数定义不 全面而带来的调用错误。为解决上述问题C++引入模板机制,模板定义:模板就是实现代码重用机制的一种工具,它可以实现类型参数化,即把类型定义为参数, 从而实现了真正的代码可重用性。模版可以分为两类,一个是函数模版,另外一个是类模版。

2.   函数模板的写法

函数模板的一般形式如下:

Template <class或者也可以用typename T>

返回类型 函数名(形参表)
{//函数定义体 }

说明: template是一个声明模板的关键字,表示声明一个模板关键字class不能省略,如果类型形参多余一个 ,每个形参前都要加class <类型 形参表>可以包含基本数据类型可以包含类类型.

请看以下程序:

//Test.cpp

#include

using std::cout;

using std::endl;

//声明一个函数模版,用来比较输入的两个相同数据类型的参数的大小,class也可以被typename代替,

//T可以被任何字母或者数字代替。

template <class T>

T min(T x,T y)

{ return(x

void main( )

{

     int n1=2,n2=10;

     double d1=1.5,d2=5.6;

     cout<< "较小整数:"<

     cout<< "较小实数:"<

     system("PAUSE");

}

程序运行结果: 

     较小整数:2

        较小实数:1.5

程序分析:main()函数中定义了两个整型变量n1 , n2 两个双精度类型变量d1 , d2然后调用min( n1, n2); 即实例化函数模板T min(T x, T y)其中T为int型,求出n1,n2中的最小值.同理调用min(d1,d2)时,求出d1,d2中的最小值.

3. 类模板的写法

定义一个类模板:

Template < class或者也可以用typename T >
class类名{
//类定义......
};

说明:其中,template是声明各模板的关键字,表示声明一个模板,模板参数可以是一个,也可以是多个。

例如:定义一个类模板:

// ClassTemplate.h

    #ifndef ClassTemplate_HH

    #define ClassTemplate_HH

    template<typename T1,typename T2>

    class myClass{

    private:

         T1 I;

         T2 J;

    public:

         myClass(T1 a, T2 b);//Constructor

         void show();

    };

    //这是构造函数

    //注意这些格式

    template <typename T1,typename T2>

    myClass<T1,T2>::myClass(T1 a,T2 b):I(a),J(b){}

    //这是void show();

    template <typename T1,typename T2>

    void myClass<T1,T2>::show()

    {

         cout<<"I="<<I<<", J="<<J<<endl;

    }

    #endif

// Test.cpp

    #include <iostream>

    #include "ClassTemplate.h"

    using std::cout;

    using std::endl;

    void main()

    {

         myClass<int,int> class1(3,5);

         class1.show();

         myClass<int,char> class2(3,"a");

         class2.show();

         myClass<double,int> class3(2.9,10);

         class3.show();

         system("PAUSE");

    }

最后结果显示:

    I=3,J=5

    I=3,J=a

    I=2.9,J=10
4.非类型模版参数

一般来说,非类型模板参数可以是常整数(包括枚举)或者指向外部链接对象的指针。

那么就是说,浮点数是不行的,指向内部链接对象的指针是不行的。

    // sequence template
    #include <iostream>
    using namespace std;

    template <class T, int N>
    class mysequence {
        T memblock [N];
      public:
        void setmember (int x, T value);
        T getmember (int x);
    };

    template <class T, int N>
    void mysequence<T,N>::setmember (int x, T value) {
      memblock[x]=value;
    }

    template <class T, int N>
    T mysequence<T,N>::getmember (int x) {
      return memblock[x];
    }

    int main () {
      mysequence <int,5> myints;
      mysequence <double,5> myfloats;
      myints.setmember (0,100);
      myfloats.setmember (3,3.1416);
      cout << myints.getmember(0) << ‘\n‘;
      cout << myfloats.getmember(3) << ‘\n‘;
      return 0;
    }

 It is also possible to set default values or types for class template parameters. For example, if the previous class template definition had been:

     template class mysequence {..};

We could create objects using the default template parameters by declaring:

     mysequence<> myseq;

Which would be equivalent to:

     mysequence myseq;

==========================

几个例子

1 交换

    #include <iostream>
    using namespace std;

    template<class X> void genericSwap( X &a, X &b ) {
            X tmp;

            tmp = a;
            a = b;
            b = tmp;
    }
    int main(void) {
            int num1 = 5;
            int num2 = 21;
            cout << "Before, num1 is " << num1 << " and num2 is " << num2 << endl;
            genericSwap( num1, num2 );
            cout << "After, num1 is " << num1 << " and num2 is " << num2 << endl;
            char c1 = ‘a‘;
            char c2 = ‘z‘;
            cout << "Before, c1 is " << c1 << " and c2 is " << c2 << endl;
            genericSwap( c1, c2 );
            cout << "After, c1 is " << c1 << " and c2 is " << c2 << endl;
            return( 0 );
    }

2 class 模板

    #include <cassert>
    #include <iostream>
    using namespace std;

    const unsigned int maxSize = 25;

    template<class T>
    class simpleStack
    {
            public:
                    simpleStack(): amount(0) {}
                    bool empty() const { return amount == 0; }
                    bool full() const { return amount == maxSize; }
                    unsigned int size() const { return amount; }
                    void clear() { amount = 0; }
                    const T& top() const;
                    void pop();
                    void push( const T &x);
            private:
                    unsigned int amount;
                    T array[ maxSize ];
    };

    template<class T>
    const T& simpleStack<T>::top() const
    {
            assert( !empty() );
            return array[ amount - 1 ];
    }

    /*it‘s allowed and equal to replace class with typename*/
            template<typename T>
    void simpleStack<T>::pop()
    {
            assert( !empty() );
            --amount;
    }

            template<typename T>
    void simpleStack<T>::push(const T &x)
    {
            assert( !full() );
            array[ amount++ ] = x;
    }

    /* main code */

    int main()
    {
            simpleStack< int > aIntStack;

            int i = 100;
            while ( !aIntStack.full() )
                    aIntStack.push( i++ );
            cout << "stack size: " << aIntStack.size() << endl;
            return 0;
    }

3 定制模板

    // template specialization
    #include <iostream>
    using namespace std;

    // class template:
    template <class T>
    class mycontainer {
            T element;
            public:
            mycontainer (T arg) {element=arg;}
            T increase () {return ++element;}
    };

    // class template specialization:
    // template <> class mycontainer <char> { ... };
    template <>
    class mycontainer <char> {
            char element;
            public:
            mycontainer (char arg) {element=arg;}
            char uppercase ()
            {
                    if ((element>=‘a‘)&&(element<=‘z‘))
                            element+=‘A‘-‘a‘;
                    return element;
            }
    };

    int main (void) {
            mycontainer<int> myint (7);
            mycontainer<char> mychar (‘j‘);
            cout << myint.increase() << endl;
            cout << mychar.uppercase() << endl;
            return 0;
    }

This is the syntax used in the class template specialization:

     template <> class mycontainer { ... };

First of all, notice that we precede the class template name with an empty template<> parameter list. This is to explicitly declare it as a template specialization.

But more important than this prefix, is the specialization parameter after the class template name. This specialization parameter itself identifies the type for which we are going to declare a template class specialization (char). Notice the differences between the generic class template and the specialization:

    1> template class mycontainer { ... };
2> template <> class mycontainer { ... };

参考

1 http://www.kuqin.com/language/20090405/44193.html

2 http://www.cplusplus.com/doc/tutorial/templates/

3 www.cppreference.com
时间: 2024-10-22 16:08:39

C++ template的相关文章

NET Core项目定义Item Template

NET Core项目定义Item Template 作为这个星球上最强大的IDE,Visual Studio不仅仅提供了很多原生的特性,更重要的是它是一个可定制的IDE,比如自定义Project Template和Item Template就是一个非常有用的扩展点.这里我们主要关注Item Template,它时我们可以在"Add new Item"对话框中添加我们自定义的Item(如下图所示).如果不了解Item Template,Scott Gu的文章. 我们之前自定义了一些Ite

手把手教你创建Azure ARM Template

Azure的ARM模式在中国已经落地了.在ARM模式中,通过ARM的Template批量的创建各种资源是与ASM模式的最大的区别之一.目前Azure ARM的Template数量已经越来越多,更多的客户会选择采用Template的模式进行资源的部署: 在前面的文章中已经介绍了如何通过已有的Template修改成你所需要的模板,请参考: http://www.cnblogs.com/hengwei/p/5634380.html 本文将一步一步的创建一个最简单的存储账户的ARM Template,并

Backbone 模板 underscore template默认的转义符&lt;%= %&gt; 与jsp的冲

先定义转义符,因为默认的转义符<%= %> 与jsp的冲突(如果js模板写在jsp页面中)       _.templateSettings = { interpolate : /\{\{(.+?)\}\}/g }; 下面就可以这样写 <script type="text/template" id="detailedBar-template"> <div class='title'> <span class='label'&

ansible的playbook配置及template模板的使用

前言: 学习下ansible的playbooks的状态配置管理,说来puppet saltstack都有类似的叫法,只是ansible的叫法更犀利,我当时一看playbook还以为是花花公子的playboy.要使用ansible就要深入学习playbook配置及模板. 注:到底是playbook还是playbooks.... 先把官网的简单几个语法给说明下. #这个是你选择的主机 - hosts: webservers #这个是变量   vars:     http_port: 80     m

Spring mvc 中使用ftl引用共通文件出错 FreeMarker template error: Error reading included file &quot;/WEB-INF/ftl/common/errormessage.ftl&quot;

初次接触spring mvc,想做一个小的练习项目,结果在ftl文件中引用其它的共通ftl文件时出错. 目录结构如图所示,想在login.ftl中引用common下的errormessage.ftl <#include '/WEB-INF/ftl/common/errormessage.ftl' /> 结果画面报错: FreeMarker template error: Error reading included file "/WEB-INF/ftl/common/errormes

Spring Boot使用thymeleaf模板时报异常:template might not exist or might not be accessible by any of the configured Template Resolvers

错误如下: template might not exist or might not be accessible by any of the configured Template Resolvers 解决方法: 1.确定模板是否在默认templates文件夹里面,并且路径要和返回的View名字一致. 2.new ModelAndView("/log/loglist");这样写是不对的,应该把开头的斜杠去掉,改成:new ModelAndView("log/loglist&

HDOJ 1217 Floyed Template

1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <cstring> 5 #include<map> 6 using namespace std; 7 8 map<string,int>name; 9 const int INF = 1000000; 10 const int MAXSIZE = 1005; 11 const int

微信小程序 模板template的使用

一.文件目录结构如下: 二.在house页面使用这些模板: 三.在house页面引入样式 四.定义模板文件 五.总结: 1.在模板文件中必须以name="模板名称" 如: <template name="HeaderNavTemplate">......</template> 包裹: 2.在引入模板页面.wxml页面中 <import src="../template/tpl-headerNav/tpl-headerNav.w

设计模式的征途—17.模板方法(Template Method)模式

在现实生活中,很多事情都需要经过几个步骤才能完成,例如请客吃饭,无论吃什么,一般都包含:点单.吃东西.买单等几个步骤,通常情况下这几个步骤的次序是:点单=>吃东西=>买单.在这3个步骤中,点单和买单大同小异,最大的区别在于第2步-吃什么?吃面条和吃满汉全席可大不相同. 在软件开发中,有时候也会遇到类似的情况,某个方法的实现需要多个步骤(类似于“请客”),其中有些步骤是固定的,而有些步骤则存在可变性.为了提高代码复用性和系统灵活性,可以使用一种称之为模板方法模式的设计模式来对这类情况进行设计.

C++中template的简单用法

模板(Template)指C++程序设计设计语言中采用类型作为参数的程序设计,支持通用程序设计.C++ 的标准库提供许多有用的函数大多结合了模板的观念,如STL以及IO Stream.使用模板可以使用户为类或者函数声明一种一般模式,使得类中的某些数据成员或者成员函数的参数.返回值取得任意类型. 一.函数模板 在c++入门中,很多人会接触swap(int&, int&)这样的函数类似代码如下: 1 void swap(int&a , int& b) { 2 int temp