`
kmplayer
  • 浏览: 508833 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

深入理解模板4

阅读更多
1,函数模板的半有序:
生成模板函数的时候,编译器将从这些模板中选择特化程度最高的模板.
template<class T> f(T):
template<class T> f(T*);
template<class T> f(const T*);
实例代码:
#include <iostream>
#include <vector>
#include <cstddef>
#include <algorithm>
using namespace std;

template<class T>
void f(T){ cout<<"f(T)"<<endl; }

template<class T>
void f(T*){ cout<<"f(T*)"<<endl; }

template<class T>
void f(const T*){ cout<<"f(const T*)"<<endl; }

int main()
{
    int i=0;
    f(i);
    f(&i);
    const int j=0;
    f(j);
    f(&j);
    return 0;
}


2,模板的显式特化:以"template<>"开头.
(1)函数模板的显式特化.
实例代码:
#include <cstring>
#include <iostream>
using namespace std;

template<typename T> const T& myMin(const T& a, const T& b)
{
    return (a < b) ? a : b;
}

/*
const char* myMin(const char* a, const char* b)
{
    return (strcmp(a, b) < 0) ? a : b;
}
*/
//可以用一个显式模板作为替代
template<>
const char* const& myMin<const char*>(const char* const& str1,const char* const& str2)
{
    return strcmp(str1,str2)<0? str1:str2;
}

int main()
{
    const char *s2 = "say \"Ni-!\"", *s1 = "knights who";
    cout << myMin(1, 2) << endl;      // (template)
    cout << myMin(s1, s2) << endl;    // (constchar*)
    cout << myMin<>(s1, s2) << endl;  // 强迫编译器使用模板,这时比较的也不是地址.
}

(2)类模板的显式特化:
template<> class vector<bool,allocator<bool> >...

3,类模板的半特化:
template<class A> class vector<bool,A>

4,类模板的半有序:
#include <iostream>
using namespace std;

template<class T,class U>
class  C
{
public:
    void f(){ cout<<"Primary Template."<<endl; }
};

template<class T,class U>
class  C<T,U*>
{
public:
    void f(){ cout<<"template<class T,class U> class  C<T,U*>."<<endl; }
};

template<class T,class U>
class  C<T*,U*>
{
public:
    void f(){ cout<<"template<class T,class U> class  C<T*,U*>."<<endl; }
};

template<class T>
class  C<T,int>
{
public:
    void f(){ cout<<"template<class T,int>"<<endl; }
};

int main()
{
    C<int,double>().f();
    C<int,double*>().f();
    C<int*,double*>().f();
    C<double,int>().f();
    return 0;
}


5,通过继承和实例化一个现存的模板来创建一个新的模板.
#include <cstring>
#include <cstddef>
#include <vector>
#include <iostream>
#include <set>
#include <iterator>
#include <ctime>
using namespace std;

class LimitRand //生成一个出现一次的随机数
{
    set<int> used;
    int limit;
public:
    LimitRand(int lim):limit(lim){}
    int operator()()
    {
        while(1)
        {
            int i=(int)(rand())%limit;
            if(used.find(i)==used.end())
            {
                used.insert(i);
                return i;
            }
        }
    }
};

template<class T> //原始模板
class Sortable:public vector<T>
{
public:
    void sort();
};

template<class T>
void Sortable<T>::sort()
{
    for(size_t i = this->size(); i > 0; --i)
        for(size_t j = 1; j < i; ++j)
            if(this->at(j-1) > this->at(j))
            {
                T t = this->at(j-1);
                this->at(j-1) = this->at(j);
                this->at(j) = t;
            }
}

template<class T> //模板的半特化
class Sortable<T*>:public vector<T*>
{
public:
    void sort();
};

template<class T>
void Sortable<T*>::sort()
{
    for(size_t i = this->size(); i > 0; --i)
        for(size_t j = 1; j < i; ++j)
            if( *(this->at(j-1)) > *(this->at(j)))
            {
                T* t = this->at(j-1);
                this->at(j-1) = this->at(j);
                this->at(j) = t;
            }
}


template<>
void Sortable<const char*>::sort()
{
    for(size_t i = this->size(); i > 0; --i)
        for(size_t j = 1; j < i; ++j)
            if( strcmp(this->at(j-1),this->at(j))>0 )
            {
                const char* t = this->at(j-1);
                this->at(j-1) = this->at(j);
                this->at(j) = t;
            }
}


char* words[] = { "is", "running", "big", "dog", "a", };
int main()
{
    srand(time(0));
    ostream_iterator<int> out_int(cout," ");
    LimitRand rnd(50);

    Sortable<int> is;
    for(size_t i = 0; i < 15; ++i)
        is.push_back(rnd());
    copy(is.begin(),is.end(),out_int);
    cout<<endl;
    is.sort();
    copy(is.begin(),is.end(),out_int);
    cout<<endl;

    Sortable<int*> ips;
    for(size_t i = 0; i < 15; ++i)
        ips.push_back(new int(rnd()));
    for(unsigned i=0;i<ips.size();i++)
        cout<<*ips[i]<<" ";
    cout<<endl;
    ips.sort();
    for(unsigned i=0;i<ips.size();i++)
        cout<<*ips[i]<<" ";
    cout<<endl;

    Sortable<const char*> scp;
    for(size_t i = 0; i < sizeof(words)/sizeof(words[0]); ++i)
        scp.push_back(words[i]);
    for(size_t i = 0; i < scp.size(); ++i)
        cout << scp[i] << ' ';
    cout << endl;
    scp.sort();
    for(size_t i = 0; i < scp.size(); ++i)
        cout << scp[i] << ' ';
    cout << endl;

    return 0;
}


6,类模板的防止模板代码膨胀机制:只有被调用的类模板的成员函数才生成代码.
实例代码:
#include <iostream>
using namespace std;

class X
{
public:
    void f(){ cout<<"X.f"<<endl; }
};

class Y
{
public:
    void g(){ cout<<"Y.g"<<endl; }
};

template<class T>
class My
{
    T t;
public:
    void useX(){ t.f(); }
    void useY(){ t.g(); }
};

int main()
{
    My<X>().useX(); //显然没有实例化成员函数useY(),否则会报错.
    //My<X>().useY();//error: 'class X' has no member named 'g'
    My<Y>().useY();
    return 0;
}


7,使用模板的原因之一是:不用手工复制代码;但是代码仍然被复制了,只不过是编译器完成这个工作.
可以将指针类型存储到某个独立的类中,可以减少程序实现的体积.
关键:用void*进行完全特化,然后从void*实现中派生出所有其他类型的指针.
#include <cassert>
#include <cstddef>
#include <cstring>
#include <iostream>
using namespace std;

//基本模板类
template<class T> class Stack
{
    T* data;
    size_t count;
    size_t capacity;
    enum { INIT = 5 };
public:
    Stack()
    {
        count = 0;
        capacity = INIT;
        data = new T[INIT];
    }
    void push(const T& t)
    {
        if(count == capacity)
        {
            size_t newCapacity = 2 * capacity;
            T* newData = new T[newCapacity];
            for(size_t i = 0; i < count; ++i)
                newData[i] = data[i];
            delete [] data;
            data = newData;
            capacity = newCapacity;
        }
        assert(count < capacity);
        data[count++] = t;
    }
    void pop()
    {
        assert(count > 0);
        --count;
    }
    T top() const
    {
        assert(count > 0);
        return data[count-1];
    }
    size_t size() const { return count; }
};

// void*完全特化
template<>
class Stack<void *>
{
    void** data;
    size_t count;
    size_t capacity;
    enum { INIT = 5 };
public:
    Stack()
    {
        count = 0;
        capacity = INIT;
        data = new void*[INIT];
    }
    void push(void* const & t)
    {
        if(count == capacity)
        {
            size_t newCapacity = 2*capacity;
            void** newData = new void*[newCapacity];
            std::memcpy(newData, data, count*sizeof(void*));
            delete [] data;
            data = newData;
            capacity = newCapacity;
        }
        assert(count < capacity);
        data[count++] = t;
    }
    void pop()
    {
        assert(count > 0);
        --count;
    }
    void* top() const
    {
        assert(count > 0);
        return data[count-1];
    }
    size_t size() const { return count; }
};

// 继承完全特化的半特化版本
template<class T>
class Stack<T*> : private Stack<void *>
{
    typedef Stack<void *> Base;
public:
    void push(T* const & t) { Base::push(t); } //这里T* const& t表示指针本身是常量
    void pop() { Base::pop(); }
    T* top() const { return static_cast<T*>(Base::top()); }
    size_t size() { return Base::size(); }
};

template<class StackType>
void emptyTheStack(StackType& stk)
{
    while(stk.size() > 0)
    {
        cout << stk.top() << endl;
        stk.pop();
    }
}

// 函数模板重载,半有序
template<class T>
void emptyTheStack(Stack<T*>& stk)
{
    while(stk.size() > 0)
    {
        cout << *stk.top() << endl;
        stk.pop();
    }
}

int main()
{
    Stack<int> s1;
    s1.push(1);
    s1.push(2);
    emptyTheStack(s1);

    Stack<int *> s2;
    int i = 3;
    int j = 4;
    s2.push(&i);
    s2.push(&j);
    emptyTheStack(s2);

    return 0;
}













分享到:
评论

相关推荐

    深入理解JavaScript系列

    深入理解JavaScript系列(4):立即调用的函数表达式 深入理解JavaScript系列(5):强大的原型和原型链 深入理解JavaScript系列(6):S.O.L.I.D五大原则之单一职责SRP 深入理解JavaScript系列(7):S.O.L.I.D...

    深入实践C++模板编程 源码

    在深入实践C++模板编程的过程中,我们不仅可以理解模板的基本概念,还可以掌握其高级特性和应用技巧。 首先,我们要理解模板的两种主要形式:函数模板和类模板。函数模板用于定义通用的函数,例如`std::swap`,它...

    VC++深入理解源码

    《VC++深入理解源码》是一本专注于解析VC++编程语言内部机制的书籍,作者孙鑫通过详尽的代码分析,带领读者深入了解VC++的源码实现,旨在提高读者对C++编译器、运行库以及相关开发工具的深度认识。这本书不仅适合有...

    深入理解c++11pdf

    《深入理解C++11》是一本专注于C++11...总的来说,《深入理解C++11》这本书详尽地探讨了C++11的新特性,包括对多态性、继承构造函数和模板使用的增强,这些改进使得C++更加强大且易用,提高了代码的可靠性和可维护性。

    电子书 深入理解C++11(PDF)

    《深入理解C++11》是一本专注于C++11标准的权威指南,旨在帮助开发者全面掌握C++11引入的新特性和改进。C++11是C++语言的一个重大更新,它带来了许多新的功能和优化,使得C++在效率、可读性和安全性方面都有了显著...

    深入SharePoint模板定制

    其强大的自定义能力是其深受用户喜爱的重要原因,而“深入SharePoint模板定制”则是这一领域的核心知识。下面将详细探讨SharePoint模板定制的相关概念、方法和实践应用。 首先,SharePoint模板是预定义的网站结构,...

    深入理解C++11.pdf

    鉴于此,我将基于标题“深入理解C++11.pdf”所暗示的内容,详细阐述C++11标准中一些核心特性的知识点。 C++11是C++语言的一个重要版本更新,正式名称为ISO/IEC 14882:2011,它在2011年被国际标准化组织正式采纳。这...

    深入理解C++对象模型

    理解模板的实例化、类型推断和模板元编程,可以让我们编写出高效且可复用的代码。 8. **异常处理**:C++的异常处理机制允许程序在遇到错误时优雅地恢复。理解异常的抛出、捕获和栈展开的过程,可以提高代码的健壮性...

    深入理解JavaScript系列(.chm)

    深入理解JavaScript系列(41):设计模式之模板方法 深入理解JavaScript系列(42):设计模式之原型模式 深入理解JavaScript系列(43):设计模式之状态模式 深入理解JavaScript系列(44):设计模式之桥接模式 ...

    《深入实践C++模板编程》(温宇杰)源码

    读者可以通过这些源码来学习如何有效地利用STL解决实际问题,理解模板的延迟特性和模板展开过程,以及如何利用模板技巧实现高效的数据结构和算法。 在深入研究C++模板编程时,会接触到一些高级主题,比如模板特化、...

    深入理解C++11完整版

    然而,我可以为您深入解释C++11语言版本的一些重要特性和设计思路,以满足您对C++11的深入理解需求。 C++11是C++编程语言的一个重大更新,它在2011年被国际标准化组织正式标准化。这个版本引入了大量新特性和改进,...

    深入理解C++11.rar

    《深入理解C++11》是一本专门为C++开发者准备的深入学习教程,它涵盖了C++11标准的全新特性和重要改进。C++11是C++编程语言的一个重大更新,引入了大量的新功能和优化,旨在提升代码的效率、可读性以及安全性。以下...

    深入学习与实践C++模板编程 值得学习

    本篇将深入探讨这两种模板的使用及其重要性。 一、函数模板 函数模板是C++中实现泛型编程的主要手段之一。它定义了一个通用函数,该函数可以在编译时根据不同的数据类型自动生成相应的实例。函数模板的基本语法如下...

    深入理解C++11

    《深入理解C++11》是一本专注于C++11标准的权威指南,该书全面地阐述了C++11的新特性和改进,为程序员提供了深入解析这一现代C++版本的宝贵资源。C++11是C++语言的一个重要里程碑,它引入了大量的新功能和优化,旨在...

    深入理解 C++ 11 PDF文档

    《深入理解C++ 11》是一本专为探索C++ 11新特性而编写的权威指南。C++ 11是C++语言的一个重要里程碑,它引入了大量的新特性和改进,旨在提升效率、安全性和可维护性,同时简化编程工作。这本书详细介绍了这些变革,...

    深入理解magento

    总结,深入理解Magento意味着要掌握其请求处理机制、页面布局设计、数据模型以及高级编程模式。这不仅需要对PHP有扎实的基础,还需要熟悉Magento的架构和设计模式。通过学习和实践,开发者能够创建出高效、可维护的...

    模板教程,模板 模板教程

    1. 模板的基础知识:理解模板的定义、类型及其在不同领域的应用。 2. HTML/CSS模板:学习如何创建和自定义HTML页面模板,以及CSS用于样式控制的重要性。 3. 响应式模板设计:探讨如何为移动设备优化模板,使其具备...

    《 C++模板》和《C++模板元编程》两本

    在《C++ Templates》这本书中,读者可以深入理解模板的基本概念,如模板声明、实例化、模板特化以及模板偏特化。书中可能涵盖了模板参数推断、模板元编程的入门知识,以及如何利用模板来实现泛型算法,如排序、查找...

    ug工程图模板 工程图模板

    本文将深入探讨UG(Unigraphics NX)软件中的工程图模板及其应用。 一、UG工程图模板概述 UG是一款强大的三维建模和工程分析软件,其工程图模块允许用户生成符合国际标准的二维工程图。工程图模板则是UG中的一个...

Global site tag (gtag.js) - Google Analytics