C++ラーニング13:テンプレートのタイプと特化

30260 ワード

前言:C++学習8:テンプレートの初歩的な理解
1テンプレートのタイプ
1.1 Class template,クラステンプレート
クラスを設計する場合、クラスで定義されたタイプは一時的に指定されません.前の勉強で話したことがありますが、テンプレートを見て入門してください.
template<typename T>
class complex
{
public:
    complex(T r = 0, T i = 0)
    : re(r), im(i)
    {}
    complex& operator += (const complex&);
    T real () const { return re; }
    T imag () const { return im; }
private:
    T re, im;

    friend complex& __doapl (complex*, const complex&);
};

{
    complex<double> c1(2.5, 1.5);
    complex<int> c2(2, 6);
    ...
}

1.2 Function template,関数テンプレート
関数を設計する場合、関数のパラメータと戻りタイプは一時的に指定されません.重要な手順は、実パラメータの導出です.前の勉強で話したことがありますが、テンプレートを見て入門してください.
template <class T>
inline const T& min(const T& a, const T& b)
{
    return b < a ? b : a;
}

class stone
{
public:
    stone(int w, int h, int we) 
    : _w(w), _h(h), _weight(we)
    { }
    bool operator< (const stone& rhs) const
    { return _weight < rhs._weight; }
private:
    int _w, _h, _weight;
};

1.3メンバーテンプレート
構文:次のプログラムではtemplateと呼ばれ、この小さなテンプレートは大きなテンプレートtemplateではメンバーテンプレートと呼ばれます.用途:外の大きなテンプレートは変化するものであることが想像でき、T 1とT 2が確定した後、中の小さなテンプレートはまた変化することができ、変化のタイプはU 1とU 2である.役割:コンストラクション関数によく使用され、コンストラクション関数をより柔軟に構築できます.
template <class T1, class T2>
struct pair
{
    typedef T1 first_type;
    typedef T2 second_type;

    T1 first;
    T2 second;

    pair()
        : first(T1()), second(T2()) {}
    pair(const T1& a, const T2& b)
        : first(a), second(b) {}
        
    template <class U1, class U2>//    , U1   T1,U2   T2。 U1    T1,U2    T2
    pair(const pair<U1, U2>& p)
        : first(p.first), second(p.second) {}
};

次のように使用します.
class Base1{};					//  Base1 “  ”
class Derived1:public Base1{};	//  Derived1 “  ”

class Base2{};					//  Base2 “  ”
class Derived2:public Base2{};	//  Derived2 “  ”

//	   T1		  T2
pair<Derived1, Derived2>p;	//    p,          
pair<Base1, Base2>p2(p);	//    p2,          

//        :         
//	  T1	 T2				U1			U2
pair<Base1, Base2>p2(pair<Derived1, Derived2>());

上の例から:フナとスズメは魚類と鳥類に入れることができ、魚類と鳥類はフナとスズメに入れることができない.(子は親に属し、親は子に属しない、すなわちup-cast:上位へ変換)例、スマートポインタshared_ptr:
template<typename _Tp>
class shared_ptr:public __shared_ptr<_Tp>
{
...
    template<typename _Tp1>
    explicit shared_ptr(_Tpl* __p)
    :__shared_ptr<_Tp>(__p){}
...    
};

Base1* ptr = new Derived1;				//   (  )  ,    ,   (           ,    ,   )
shared_ptr<Base1>sptr(new Derived1);	//  up-cast


2 specialization、テンプレート特化
2.1汎化と特化
汎化はfull specializationです.特化した反意語は汎化である.汎化はテンプレートの特徴で、1つのタイプを表し、使うときに指定すればいいです.特化はいくつかの独特なタイプに対して特殊な設計をしなければならない.テンプレートの1つまたはいくつかのタイプを固定することである.形式:template<>、尖った括弧の中に何もありません.例:
//  :
template <class Key>
struct hash{ };

//  :
template<>
struct hash<char>
{
    size_t operator() (char x) const { return x; }
};

template<>
struct hash<int>
{
    size_t operator() (int x) const { return x; }
};

template<>
struct hash<long>
{
    size_t operator() (long x) const { return x; }
};

使用は簡単です.
cout << hash() (1000);

2.2 patial specialization,テンプレート局所特化(偏特化)
2.2.1個の数の偏り
汎化タイプ:
template<typename T, typename Alloc=...>
class vector
{
    ...
};

特殊な設計のために,Tをboolタイプにバインドし,これに偏り,特殊な設計を定義することができる.
template<typename Alloc=...>
class vector<bool, Alloc>
{
    ...

2.2.2範囲の偏り
汎化タイプ:
template <typename T>
class C
{
    ...
};

ポインタタイプのみを特化処理するには、使用者が使用するタイプがポインタのみである場合、次の特化バージョンを呼び出す必要があります.
template <typename U>
class C<U*>//            
{
    ...
};

C<string> obj1;		//            
C<string*> obj2;	//            

3 template template parameter,テンプレートテンプレートパラメータ
template<typename T, 
        template <typename T>	//      :        ,         
            class Container		//  ,      :        ,         
        >
class XCls
{
private:
    Container<T> c;//           
public:
    ......
};
template<typename T>
using Lst = list<T, allocator<T>>;

//    T  
XCls<string, list> mylst1;//       ,        string。   ,       。
XCls<string, Lst> mylst2;//  

例:
template<typename T,
            template <typename T>	//      
                class SmartPtr		//      
        >
class XCls
{
private:
    SmartPtr<T> sp;
public:
    XCls():sp(new T) { }
};

XCls<string, shared_ptr> p1;
XCls<string, unique_ptr> p2;//  ,  ,     
XCls<int, weak_ptr> p3;//  ,  ,     
XCls<long, auto_ptr> p4;

反例:2番目のテンプレートパラメータはテンプレートではありません.バインドは決定されました.
template <class T, class Sequence = deque<T>>
class stack
{
    friend bool operator== <> (const stack&, const stack&);
    friend bool operator< <> (const stack&, const stack&);

protected:
    Sequence c;//    
......
};

stack<int> s1;
stack<int, list<int>> s2;