泛型编程深入探索(二) 模板递归与可变参数模版

以构建一个n纬网格为例,讲述模板递归。

首先是一个简单的一纬网格的实现,这个网格实现了规定长度的网格的实例化,并且能够在不同大小的网格类中自由的转型(通过模版嵌套的cast_ctr)

(使用到的技术,非类型参数模版,模版嵌套,类模版特例化,模版友元函数)

#include <cassert>
#include <iostream>

using namespace std;
template <typename T,int LENGTH>
class grid;

template <typename T,int LENGTH>
ostream& operator<< (ostream& os, const grid<T, LENGTH>& gd){
    os<<"[[grid with size: "<<gd.getSize()<<"] ";
    for(int i=0;i<gd.getSize()-1;i++){
        os<<gd[i]<<"\t";
    }
    os<<gd[gd.getSize()-1]<<"]"<<endl;
    return os;
}

template <typename T,int LENGTH>
class grid{
public:
    grid():size(0),mCells(new T[LENGTH]){};
    grid(const grid<T,LENGTH>& gd):mCells(new T[LENGTH]),size(gd.size){
        for(int i=0;i<gd.size;i++){
            mCells[i]=gd.mCells[i];
        }
    }
    //足够,任何修改了t或者length的都会被这个嵌套模板handle
    template<typename E, int NEWLENGTH>
    //required E->T naturally
    grid(const grid<E,NEWLENGTH>& gd):mCells(new T[LENGTH]),size(0){
        int newSize=LENGTH>gd.getSize()?gd.getSize():LENGTH;
            for(int i=0;i<newSize;i++){
                *(mCells+i)=gd[i];
            }
            size=newSize;
    }
    grid<T,LENGTH>& operator=(const grid<T,LENGTH>& gd){
        size=gd.getSize();
        T* su1= mCells;
        T* su2= gd.mCells;
        while(su1!=mCells+gd.size-1){
            *su1++=*su2++;
        }
    }
    template<typename E, int NEWLENGTH>
    //required E->T naturally
    grid<T,LENGTH>& operator=(const grid<E,NEWLENGTH>& gd){
        int newSize=LENGTH>gd.getSize()?gd.getSize():LENGTH;
        for(int i=0;i<newSize;i++){
            *(mCells+i)=gd[i];
        }
        size=newSize;
    }
    inline int getSize()const {return size;}
    virtual ~grid(){delete mCells;mCells=nullptr;};
    T& operator[](int index){
        if(index>=size){
            resize(index+1);
        }
        return *(mCells+index);
    }
    const T& operator[] (int index)const{
        assert(index<getSize());
        return *(mCells+index);
    }
    void resize(int newSize,const T& def=T()){
        assert(newSize<=LENGTH);
        if(newSize<=size){
            size=newSize;
        }
        else {
            int i=size;
            for(;i<=newSize-1;i++){
                *(mCells+i)=def;
            }
            size=newSize;
        }
    }
    friend ostream& operator<< <T,LENGTH>(ostream& os, const grid<T, LENGTH>& gd);
private:
    T* mCells;
    int size;
};

测试代码如下:

#define     _TEST_GRID_      1
#if         _TEST_GRID_

#include "grid.h"
#include <iostream>
#include <ctime>
#include <cstdio>
using namespace std;
int main(){

    //网格实例化
    grid<int,20> a;
    srand((int)time(NULL));
    for(int i=0;i<20;i++){
        a[i]=rand()%30;
    }
    //不同大小,不同类型的网格互相拷贝
    grid<double,40>b(a);
    grid<double,10>c(a);
    cout<<a<<b<<c;
    //利用一纬网格,由调用方实现模版递归(实际是实例递归)
    grid<int,40> onegrid;
    grid<grid<int, 40>, 40> twogrid;
    unsigned long lct=time(NULL);
    for(int k=0;k<40;k++){
        srand((unsigned)(lct-clock()));
        for(int i=0;i<20;i++){
            twogrid[k][i]=rand()%30;
        }
    }
    cout<<twogrid;
}

#endif

本栏目更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/Programming/project/

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索递归
, 友元
, 网格
, 参数
, 泛型编程
, 模板
, 可变参数
, template
, 可变参数class
, 深入探索c
, 模版
, 特例化
递归编程
java 泛型递归模式、深入理解java泛型详解、泛型 模板、c 模板 泛型、泛型和模板,以便于您获取更多的相关知识。

时间: 2024-09-17 04:47:00

泛型编程深入探索(二) 模板递归与可变参数模版的相关文章

函数模板,函数模板重载,可变参数模板,函数模板覆盖,通过引用交换数据

 1.函数模板初级,如果想使用模板,需要实例化,实例化的方式是加上<数据类型> #include <iostream>   //函数模板可以对类型进行优化重载,根据类型会覆盖 //如果仍然要使用模板函数,需要实例化   template<class T> T add(T a, T b) {     std::cout << "T add " << std::endl;     return a + b; }   int a

求变量的数据类型,typeid,bool,C和C++的不同,new和delete,C++中的枚举,inline和可变参数模板,auto和函数模板,宽字符

求变量的数据类型,通过函数typeid(变量名).name();获得变量的数据类型. 案例如下: #include<iostream> #include<stdlib.h>   voidmain() {    doubledb = 10.9;    double *pdb = &db;    autonum =pdb;    //通过typeid的方式获得数据类型    std::cout << typeid(db).name() << std::e

泛型编程深入探索(一) 模版高级特性小结

一些基本的模版特性: 非类参数模版 模版所声明的参数可以不是类参数,可以声明的非类参数包括整数(double,float不可以),enum,对象引用或指针. 通过模版嵌套实现类或非类参数载类方法参数上的重载(调用时实现,不在定义时实现) 友元函数模版: 直接举例: template <typename T> friend ostream& operator<< <T>(ostream& os, const T& t){}; 内联模版函数: 模版定

Lua中的函数(function)、可变参数、局部函数、尾递归优化等实例讲解_Lua

一.函数 在Lua中,函数是作为"第一类值"(First-Class Value),这表示函数可以存储在变量中,可以通过参数传递给其他函数,或者作为函数的返回值(类比C/C++中的函数指针),这种特性使Lua具有极大的灵活性.   Lua对函数式编程提供了良好的支持,可以支持嵌套函数.   另外,Lua既可以调用Lua编写的函数,还可以调用C语言编写的函数(Lua所有的标准库都是C语言写的).   定义一个函数 复制代码 代码如下: function hello() print('he

Python入门(四)——函数概述,参数,可变参数,关键字参数,组合参数,递归函数

Python入门(四)--函数概述,参数,可变参数,关键字参数,组合参数,递归函数 Hello,各位,我们继续来学习python 一.函数概述 函数,就是方法嘛,其实在我们之前就已经接触过了,看一下代码 #求长度 print len(["xx", "yy"]) #求绝对值 print abs(-2) 在这段代码中,这个len()和abs()就是函数 而且有意思的是,函数可以赋值 a = abs print a(-2) 这也是可以的 二.函数参数 那我们会使用了,我们

java-[Java]关于重载方法中的可变参数列表

问题描述 [Java]关于重载方法中的可变参数列表 <Thinking in Java>第105页有一句话不理解 如何理解你应该总是只在重载方法的一个版本上使用可变参数列表,或者压根就不是用它 解决方案 就是当重载一个方法时,选择其中的一个重载使用可变参数,其他的避免使用,否则编译的时候容易出问题.具体的参看http://www.cnblogs.com/lanxuezaipiao/p/3190673.html 解决方案二: 这个道理很简单,比如说你有foo(int x int ... args

c/c++支持可变参数的函数

一.为什么要使用可变参数的函数? 一般我们编程的时候,函数中形式参数的数目通常是确定的,在调用时要依次给出与形式参数对应的所有实际参数.但在某些情况下希望函数的参数个数可以根据需要确定,因此c语言引入可变参数函数.这也是c功能强大的一个方面,其它某些语言,比如fortran就没有这个功能. 典型的可变参数函数的例子有大家熟悉的printf().scanf()等. 二.c/c++如何实现可变参数的函数? 为了支持可变参数函数,C语言引入新的调用协议, 即C语言调用约定 __cdecl . 采用C/

[C++]遍历可变参数 (va_list)

前言 在C++中使用可变参数可没C#中那么方便,使用起来也很麻烦,想尽办法搜了很多资料仍然无果,但是确有一些心得.   文章 1. http://www.programmer-club.com.tw/ShowSameTitleN/vc/13915.html 2. va_list.va_start.va_arg.va_end的原理与使用   正文 一. 遍历可变参数 1.1 传入的时候指定参数个数 void arg_cnt(int cnt, ...) {     int value=0;     

class-c语言定义一对一对的可变参数函数

问题描述 c语言定义一对一对的可变参数函数 fund(type_1 data_1 type_2 data_2 ...); 类似这样的函数怎样定义. 解决方案 http://www.cnblogs.com/MarvinGeng/archive/2012/07/19/2598923.html 解决方案二: 定义一个参数数组作为一个参数 解决方案三: typedef struct field_pad{ UINT1 type; UINT1 len; INT1 pad[62];}field_pad_t;