c++におけるテンプレートの実装(テンプレートクラスとテンプレート関数)


[TOC]
かたわく
 交換関数を実装すると、次のように書くことができます.
void Swap(int& x, int& y)
{
    int tmp = x;
    x = y;
    y = tmp;
}

ここでは2つの整数しか交換できません.2つの文字交換を実現する必要がある場合は、関数を書き直す必要がありますが、2つのコードには同じ部分がたくさんあります.これは面倒ではありません.コードを1部書くだけで異なるタイプの交換を実現できるなら、素晴らしいのではないでしょうか.はい、このコンパイラは私たちに設計してくれました.これはいわゆる汎用プログラミングです.テンプレートは汎用プログラミングの基礎であり,汎用プログラミングとはタイプに関係のない論理コードを記述し,多重化する方式である.
一、テンプレート関数
テンプレート関数のフォーマット:
template戻りタイプ関数名(パラメータリスト){...} class, typename, 。さっきのSwap関数はテンプレート関数でできます.
テンプレートパラメータの暗黙的インスタンス化
template
void Swap(T& x, T& y)
{
    T tmp = x;
    x = y;
    y = tmp;
}

複数のタイプの交換が可能かどうかを確認し、テスト結果を確認します.
これがテンプレート関数の実装です.もちろん、なぜ関数が1つで済むのか知りたいです.実際には最下位で関数の再ロードが実現されており,アセンブリコードに移動すると分かる.
int main()
{
00394D30  push        ebp  
00394D31  mov         ebp,esp  
00394D33  sub         esp,114h  
00394D39  push        ebx  
00394D3A  push        esi  
00394D3B  push        edi  
00394D3C  lea         edi,[ebp-114h]  
00394D42  mov         ecx,45h  
00394D47  mov         eax,0CCCCCCCCh  
00394D4C  rep stos    dword ptr es:[edi]  
00394D4E  mov         eax,dword ptr [__security_cookie (039A000h)]  
00394D53  xor         eax,ebp  
00394D55  mov         dword ptr [ebp-4],eax  
    int a1 = 1, a2 = 2;
00394D58  mov         dword ptr [a1],1  
00394D5F  mov         dword ptr [a2],2  
    Swap(a1, a2);
00394D66  lea         eax,[a2]  
00394D69  push        eax  
00394D6A  lea         ecx,[a1]  
00394D6D  push        ecx  
00394D6E  call        Swap (039137Ah)  
00394D73  add         esp,8  
    char c1 = 5, c2 = 6;
00394D76  mov         byte ptr [c1],5  
00394D7A  mov         byte ptr [c2],6  
    Swap(c1, c2);
00394D7E  lea         eax,[c2]  
00394D81  push        eax  
00394D82  lea         ecx,[c1]  
00394D85  push        ecx  
00394D86  call        Swap (0391375h)  
00394D8B  add         esp,8  
    double d1 = 1.222, d2 = 2.011111111111;
00394D8E  movsd       xmm0,mmword ptr [__real@3ff38d4fdf3b645a (0397BD0h)]  
00394D96  movsd       mmword ptr [d1],xmm0  
00394D9B  movsd       xmm0,mmword ptr [__real@400016c16c16c072 (0397BD8h)]  
00394DA3  movsd       mmword ptr [d2],xmm0  
    Swap(d1, d2);
00394DA8  lea         eax,[d2]  
00394DAB  push        eax  
00394DAC  lea         ecx,[d1]  
00394DAF  push        ecx  
00394DB0  call        Swap (039137Fh)  
00394DB5  add         esp,8  
    return 0;
00394DB8  xor         eax,eax  
}

 下位層では、Swap関数を呼び出すたびにスタックフレームが確立され、スタックフレームが確立されるたびに、パラメータのタイプが異なり、スタックフレームが確立されるのも異なることがわかる.テンプレートを使用すると、コンパイラはコンパイル前に行われる推論プロセスを行います.推論すると、コンパイラは、伝達パラメータのタイプに応じて対応する関数をインスタンス化( )してコンパイルしています.たとえば、
template //  class   typename     
void Swap(T1& x,T2& y)
{
    T1 tmp = x;
    x = y;
    y = tmp;
}

時々私たちはこのような奇抜な問題に直面するかもしれません.
template< class T>
const T Add(T& x,T& y)
{
    return x+y;
}

このように呼び出すとSwap(1,1.2302102);、コンパイラはどのようにインスタンス化されますか?
テンプレートパラメータ表示のインスタンス化
これは、指定されたインスタンス化タイプ Add Add(1,5.222222);(1.5.222222)を表示しなければならないことに関する.これでさっきの問題を解決することができます.
二、テンプレート類
テンプレートクラスのフォーマット
template
class   
{ ... };

c++でシーケンステーブルとチェーンテーブルを書き始める前に、私たちはそうでした.
typedef int Datatype;

typedef struct SeqList
{
    struct SeqList* _data;
    size_t _size;
}SeqList;

typedef struct ListNode
{
    struct ListNode* _prev;
    struct ListNode* _next;
    Datatype _data;
}ListNode;

このようにシーケンステーブルとチェーンテーブルを定義しますが、次のような大きな問題があります.
1つのプログラムで2つの異なるデータ型シーケンステーブルとチェーンテーブルを使用する場合、各タイプが1つのタイプを定義しない限り、完了できません.
<double>

typedef int Datatype; // int

typedef struct SeqList
{
struct SeqList* _data;
size_t _size;
}SeqList;

typedef struct ListNode
{
struct ListNode _prev;
struct ListNode
_next;
Datatype _data;
}ListNode;

typedef char Datatype; // char  

typedef struct SeqList
{
    struct SeqList* _data;
    size_t _size;
}SeqList;

typedef struct ListNode
{
    struct ListNode* _prev;
    struct ListNode* _next;
    Datatype _data;
}ListNode;

, , 。

template
class Vector
{
public:
    Vector():_first(NULL),_finish(NULL),_endofstorge(NULL)//    
    {}
    ~Vector()//    
    {
        delete[]_first;
        _first = _finish = _endofstorge = NULL;
    }
    Vector(const Vector& v)//    
        :_first(NULL)
        ,_finish(NULL)
        ,_endofstorge(NULL)
    {
        int len = v._finish - v._first;
        _first = _finish = new T[len];
        T* start = v._first;
        while(start != v._finish)
        {
            *(_finish) = *start;
            ++_finish;
            ++start;
        }
        _endofstorge = _first+len;
    }

    Vector& operator=(Vector& v) //       
    {
        delete[]_first;
        Vector v1(v);
        swap(_first ,v1._first);
        swap(_finish , v1._finish);
        swap(_endofstorge , v1._endofstorge);

        return *this;
    }

    void PushBack(const T& x) //  
    {
        if(_finish == _endofstorge)
            Expand(Capacity()*2+1);
        _first[Size()] = x;
        ++_finish;
    }
    void PopBack()//  
    {
        Erase(Size()-1);
    }
    void Expand(size_t n) //  
    {
        int size = Size();
        if(n>Capacity())
        {
            T* tmp = new T[n];
            for (int i = 0;i

void VectorTest()
{
    Vector v;
    v.PushBack(1);
    v.PushBack(2);
    v.PushBack(3);
    v.PushBack(4);
    v.PushBack(5);
    v.PushBack(6);
    v.PushBack(7);
    PrintVocter(v);

    Vector v1;
    v1.PushBack("hello");
    v1.PushBack("world !");
    v1.PushBack("i");
    v1.PushBack("love");
    v1.PushBack("you");
    PrintVocter(v1);

}


#ifndef __LIST_H__
#define __LIST_H__

#include
#include
using namespace std;

template 
struct ListNode
{
    struct ListNode* _prev;
    struct ListNode* _next;
    T _data;

};

template 
class List
{
    typedef ListNode Node;
public:
    List()//    
    {
        _head = new Node;
        _head->_next = _head->_prev = _head;
    }
    List(const List& h) //    
    {
        Node* head = h._head;
        Node* tmp = head->_next;

        _head = new Node;
        _head->_next = _head->_prev = _head;
        while (tmp != head)
        {
            PushBack(tmp->_data);
            tmp = tmp->_next;
        }
    }
    ~List() //    
    {
        Clear();
        delete _head;
        _head = NULL;
    }
    void PushBack(const T& x) //  
    {
        Node *tmp = new Node;
        tmp->_data = x;
        Node* tail = _head->_prev;

        tail->_next = tmp;
        tmp->_prev = tail;
        _head->_prev = tmp;
        tmp->_next = _head;

    }
    void PushFront(const T& x) //  
    {
        Node *tmp = new Node;
        tmp->_data = x;
        Node* cur = _head->_next;
        tmp->_prev = _head;
        _head->_next = tmp;
        tmp->_next = cur;
        cur->_prev = tmp;
    }
    void PopBack() //  
    {
        Node* cur = _head->_prev;
        _head->_prev = cur->_prev;
        cur->_prev->_next = _head;

        delete[]cur;
        cur->_next = cur->_prev = NULL;
    }
    void PopFront() //  
    {
        Node* cur = _head->_next;
        _head->_next = cur->_next;
        cur->_next->_prev = _head;
    }
    void Insert(Node* pos,const T& x) //    
    {
        Node* cur = new Node;
        cur->_data = x;
        cur->_prev = pos->_prev;
        pos->_prev->_next = cur;
        pos->_prev = cur;
        cur->_next = pos;
    }
    void Erase(Node* pos) //      
    {
        Node* cur = pos->_next;
        pos->_prev->_next = cur->_next;
        cur->_next->_prev = pos->_prev;
    }
    void Clear() //      
    {
        Node* cur = _head->_next;
        while(cur != _head)
        {
            Node* tmp = cur;
            cur = cur->_next;
            delete tmp;
        }
        _head->_next = _head;
        _head->_prev = _head;
    }
    Node* Find(const T& x) //  
    {
        Node* cur = _head->_next;
        while (cur != _head)
        {
            if(cur->_data==x)
                return cur;
            cur = cur->_next;
        }
        return NULL;
    }

    size_t Size() //      
    {
        size_t count = 0;
        Node* cur = _head->_next;
        while (cur != _head)
        {
            count++;
            cur = cur->_next;
        }
        return count;
    }
    bool Empty()
    {
        if (_head->_next = _head->_prev)
            return 1;
        return 0;
    }
    void PrintList() //    
    {
        Node* tmp = _head->_next;
        while (tmp != _head)
        {
            std::cout<_data<_next;
        }
        std::cout<<:endl protected:="" node="" _head=""/>