zoukankan      html  css  js  c++  java
  • 模板特化

    前言:

    C++提供了一种特例机制,对于某个已有模板,可以为某个或者某组模板参数类型另外指定一种变体,以应付原模板无法处理的问题,或者提供更高效的实现方案.这种机制就称为模板特例.

     

    模板特例一个典型的例子就是C++标准库中的容器类模板vector<T>。与数组相似,vector是一种将数据连续存放的容器.但与数组不同的是,vector容量可随所存数据增加而自动增加.vecotr<bool>则是vector<T>的一个特例,专门为存储布尔型值设计.布尔型只有两个值,真或者假,只需要1比特即可表示.1字节完全可以用来存储8个布尔型变量.如果采用基于sizeof(T)的算法,则1个布尔值占用1字节,显得太浪费.

    我们将vector<bool>设计成用一系列整数值来保存压缩后的布尔值.

    具体见代码:

    #include <cstdio>
    #include <iostream>
    #include <stdexcept>
    
    template<typename T>
    class my_vector{
    private:
         T * array;
         unsigned size;
         unsigned block_size;
    public:
        my_vector(unsigned bsz):array((T*)malloc(sizeof(T)*block_size),size(0),
                                  block_size(size){
                                  }
        ~my_vector(){
             if(array){
                   free(array);
             }
        }
        
        void push_back(const T& v) throw (std::runtime_error){
               if(size==block_size){
                      block_size*=2;
                      T *new_array=realloc(array,block_size*sizeof(T));
                      if(new_array!=NULL){
                            array=new_array;
                      }
                      
                      else{
                             free(array);
                             array=NULL;
                             throw std::runtime_error("Out of memory.");
                      }
               }
               array[size++]=elem;
        }
        
        T& operator[] (unsigned i) {return array[i];}
        const T& operator[] (unsigned i) const{return array[i];}
        
        //告诉我们占了多少内存
        unsigned get_mem_size() const{return block_size*sizeof(T);}
    };
    
    
    template<>
    class my_vector<bool>{
    private:
           int *array;
           unsigned size;
           unsigned block_size;
           //一个段(segment)即一个整数值,段大小为一个整数值所能容纳的最多布尔值
           const static unsigned seg_size;
    public:
           my_vector(unsigned bsz):array((int*)malloc(sizeof(int)*bsz),size(0),
                                                           block_size(bsz){
                                                           }
           
           ~my_vector(){
                  if(array){
                        free(array);
                  }
           }
           
           void push_back(bool elem) throw (std::runtime_error){
                   if(size==block_size){
                         block_size*=2;
                         int *new_array=(int*)realloc(array,sizeof(int)*block_size);
                         if(new_array){
                               array=new_array;
                         }
                         
                         else{
                              free(array);
                              array=NULL;
                              throw std::runtime_error("Out of memory.");
                         }       
                   }
                   
                  set(size++,elem);
          }
          
          void set(unsigned i,bool elem){
                 if(elem){
                       array[i/seq_size] |=(0x1 << (i%seq_size));
                 }
                 
                 else{
                       array[i/seq_size] &=~(0x1 << (i%seq_size));
                 }
          }
          
          bool operator[] (unsigned i) const{
                 return array[i/seq_size] & (0x1 << (i%seq_size))!=0;
          }
          
          unsigned get_mem_size() const{
                return block_size* sizeof(int);
          }
    };
    
    const unsigned my_vector<bool>::seq_size =sizeof(int)*8;
        

     面试题:

     在软件公司的招聘考试中,经常出现的C/C++题目是:不使用循环及条件判断语句,打印1-100的数字.

     思路如下:

     这个问题可以通过采用编译器的递归调用来轻松解决问题.

    •  首先,既然不能采用循环的方式来打印,就只能采用"分而治之"的策略.那么"打印1~100的数"可以分解为"打印1~99的数"及"打印100的数"两个问题.依次类推,  则该问题显然可以通过递归来实现。
    • 模板特例实际上也是实现了一种条件判断逻辑-当模板参数满足某一匹配条件时所匹配的特例实现,否则用通例来实现.并且由于模板通例及特例是分别写在多个模板实现代码中,并不需要增加任何判断语句。

    注意:

       不过模板特例所实现的判断逻辑是在编译器来执行,而不是在程序运行时基于输入值来判断,这就要求判断式的值在编译器已知.

    解题思路还是按照递归方式,只是将递归函数改写成函数模板,将打印范围由函数参数变为模板参数.

    代码:

    #include <iostream>
    
    template<int i>
    void print(){
         print<i-1>();
         std::cout<<i<<std::endl;
    }
    
    //递归,终止递归
    template<>
    void print<1>(){
        std::cout<<1<<std::endl;
    }
    
    int main(){
        print<100>();
    }

     

  • 相关阅读:
    反射自动填充model
    source control tool
    项目管理案例分析
    IOC
    js framework
    WPF 难点内容
    WPF MVVM
    NewSQL
    软件部门员工考核
    JavaScript 中级
  • 原文地址:https://www.cnblogs.com/sixue/p/4002663.html
Copyright © 2011-2022 走看看