レッスン60-配列クラステンプレート


一、予備知識
テンプレートパラメータは、数値クラスパラメータ(非タイプパラメータ)でも構いません.
template <typename T,int N>
void func(){
  T a[N];       //            
}
···
func<double,10>();

数値型テンプレートパラメータの制限
  • 変数はテンプレートパラメータ
  • として使用できない.
  • 浮動小数点数はテンプレートパラメータ
  • として使用できない.
  • クラスオブジェクトはテンプレートパラメータ
  • として使用できません.
    本質:テンプレートパラメータはコンパイル段階で処理されるユニットであるため、コンパイル段階で正確に一意に決定しなければならない.
    プログラミング実験:面白い面接問題
    #include
    using namespace std;
    
    template < typename T,int N>
    void func(){
        T a[N] = {0};
        for(int i = 0;i < N;++i){
            a[i] = i;
        }
        for(int i = 0;i < N;++i){
            cout << a[i] << endl;
        }
    }
    
    template <int N>
    class Sum{
        public:
            static const int Value = Sum1>::Value + N;
    };
    
    template <>
    class Sum <1>{
        public:
            static const int Value = 1;
    };
    
    int main(){
        cout << "1 + 2 + 3 + ···+ 10 = " << Sum<10>::Value << endl;
        cout << "1 + 2 + 3 +  ···+ 100 = " << Sum<100>::Value << endl; 
        return 0;
    } 

    印刷結果:
    1 + 2 + 3 + ···+ 10 = 55
    1 + 2 + 3 +  ···+ 100 = 5050

    まとめ:効率的と考えられるのは,数値型テンプレートパラメータが実際にコンパイル段階で処理されるユニット,すなわちSum<10>::Valueがコンパイル時にすでに得られており,プログラムの実際の実行時には「定数」を読み取るだけであるからである.
    二、配列テンプレートクラス
    #ifndef _ARRAY_H_
    #define _ARRAY_H_
    
    template <typename T,int N>
    class Array{
        T m_array[N];
        public:
            int length();
            bool set(int index,T value);
            bool get(int index,T& value);
            T& operator[](int index);
            T operator[] (int index) const;
            virtual ~Array();
    };
    
    template <typename T,int N>
    int Array::length(){
        return N;
    }
    
    template <typename T,int N>
    bool Array::set(int index,T value){
        bool ret = (0 <= index) && (index < N);
        if( ret ){
            m_array[index] = value;
        }
        return ret;
    }
    
    template <typename T,int N>
    bool Array::get(int index,T& value){
        bool ret = (0 <= index) && (index < N);
        if( ret){
            value = m_array[index];
        }
        return ret;
    }
    
    template <typename T,int N>
    T Array::operator[] (int index) const{
        return m_array[index];
    }
    
    template <typename T,int N>
    Array::~Array(){
    }
    
    #endif

    三、スタック配列テンプレートクラス
    #ifndef _HEAPARRAY_H_
    #define _HEAPARRAY_H_
    
    template <typename T>
    class HeapArray{
        private:
            int m_length;
            T* m_pointer;
    
            HeapArray(int len);
            HeapArray(const HeapArray& obj);
            bool construct();
        public:
            static HeapArray* NewInstance(int length);
            int length();
            bool get(int index,T& value);
            bool set(int index,T value);
            T& operator [] (int index);
            T operator [] (int index) const;
            HeapArray& self();
            ~HeapArray(); 
    };
    
    template <typename T>
    HeapArray::HeapArray(int len)
    {
        m_length = len;
    }
    
    template <typename T>
    bool HeapArray::construct(){
        m_pointer = new T[m_length];
        return m_pointer != NULL;
    }
    
    template <typename T>
    HeapArray* HeapArray::NewInstance(int length){
        HeapArray* ret = new HeapArray(length);
        if(!(ret && ret->construct())){
            delete ret;
            ret = 0;
        }
        return ret;
    }
    
    template <typename T>
    int HeapArray::length(){
        return m_length;
    }
    
    template <typename T>
    bool HeapArray::get(int index,T& value){
        bool ret = (0 <= index) && (index < length());
        if( ret ){
            value = m_pointer[index];
        }
        return ret;
    }
    
    template <typename T>
    bool HeapArray::set(int index,T value){
        bool ret = (0 <= index) && (index < length());
        if( ret ){
            m_pointer[index] = value;
        }
        return ret;
    }
    
    template <typename T>
    T& HeapArray::operator [] (int index){
        return m_pointer[index];
    }
    
    template <typename T>
    T HeapArray::operator [] (int index) const{
        return m_pointer[index];
    }
    
    template <typename T>
    HeapArray& HeapArray::self(){
        return *this;
    }
    
    template <typename T>
    HeapArray& HeapArray::self(){
        return *this;
    }
    
    template <typename T>
    HeapArray::~HeapArray(){
        delete[] m_pointer;
    }
    
    #endif

    主関数:main.cpp
    #include 
    #include 
    #include "Array.h"
    #include "HeapArray.h"
    
    using namespace std;
    
    int main()
    {
        Array<double, 5> ad;
    
        for(int i=0; ifor(int i=0; icout << ad[i] << endl;
        }
    
        cout << endl;
    
        HeapArray<char>* pai = HeapArray<char>::NewInstance(10);
    
        if( pai != NULL )
        {
            HeapArray<char>& ai = pai->self();
    
            for(int i=0; i'a';
            }
    
            for(int i=0; icout << ai[i] << endl;
            }
        }
    
        delete pai;
    
        return 0;
    }

    四、まとめ
  • テンプレートパラメータは、数値型パラメータ
  • であることができる.
  • 数値型テンプレートパラメータは、コンパイル中に
  • を一意に決定する必要があります.
  • 配列クラステンプレートパラメータは、数値型テンプレートパラメータに基づいて実現する
  • である.
  • 配列クラステンプレートは簡易な線形テーブルデータ構造
  • である.