C++Primer第5版の第16章テンプレートと汎用プログラミング


第16章テンプレートと汎用プログラミング
テンプレートの定義
関数テンプレート
  • テンプレート定義はキーワードtemplateで始まり、1つのテンプレートパラメータリスト(カンマで区切られた1つ以上のテンプレートパラメータのリスト)と<>で囲まれます.
  • テンプレート定義では、テンプレートパラメータのリストを空にすることはできません.
  • template 
    int compare(const T &v1, const T &v2)
    {
        if (v1 < v2)   return -1;
        if (v2 < v1)   return 1;
        return 0;
    }
  • 実体化関数テンプレート:templateを呼び出すと、コンパイラは実体パラメータのタイプを使用してテンプレートパラメータTにバインドされたタイプを決定し、その後、コンパイラは推定されたテンプレートパラメータを使用して特定のバージョンの関数を実体化する.
  • テンプレートタイプパラメータ:キーワードclassまたはtypenameを使用してテンプレートタイプパラメータを指定します(typenameがよく使用されます).
  • template
    calc(const T&, const U&);
  • 非タイプパラメータ:タイプではなく値を表し、キーワードclassまたはtypenameではなく特定のタイプ名で指定します.
  • テンプレートがインスタンス化されると、非タイプパラメータは、ユーザが提供する値またはコンパイラによって推定された値に置き換えられ、これらの値は定数式でなければならない.
  • 非タイプのテンプレートパラメータのテンプレート実パラメータは定数式である必要がある.

  • template 
    int compare(const char (&p1)[N], const char (&p2)[M])
    {
        return strcmp(p1,p2);
    }
    compare("Hi", "Mom");
  • 関数テンプレートはinlineまたはconstexprとして宣言することができ、inlineまたはconstexpr説明子はテンプレートパラメータリストの後に配置され、タイプを返す前に
  • テンプレートコンパイル:テンプレートの特定のバージョンをインスタンス化すると、コンパイラはコードを生成します.関数テンプレートとクラステンプレートメンバー関数の定義は、通常、ヘッダファイルに配置されます.

  • クラステンプレート
  • は、コンパイラがクラステンプレートのテンプレートパラメータタイプを推定することができず、パラメータタイプを明示的に提供する必要がある点で、クラスの青写真を生成するために使用される.
  • template
    class Blob {
    public:
        //...
    private:
        std::shared_ptr<:vector>> data;
    };
    Blob ia;
  • クラステンプレートを使用する場合、テンプレートパラメータにバインドされたテンプレートの実パラメータを表示する追加情報を提供する必要があります.コンパイラは、これらのテンプレート実パラメータを使用して特定のクラスをインスタンス化します.
  • クラステンプレートの各インスタンスは、独立したクラスを形成する.インスタンス化されたBlobは、他のBlobタイプに関連付けられておらず、他のBlobタイプのメンバーに特別なアクセス権を持つこともありません.
  • クラステンプレートのコード別のテンプレートが使用されている場合、通常、インスタンスタイプの名前はテンプレートの実パラメータとして使用されず、逆にテンプレート自体のパラメータは使用されるテンプレートの実パラメータとして使用されます.
  • //             
    std::shared_ptr> data;    //T Blob     
    
  • クラス外でメンバー関数を定義する場合は、キーワードtemplateで開始し、クラステンプレートパラメータのリストに続く必要があります.また、メンバーがどのクラスに属しているかを説明する必要があります.
  • template 
    void Blob::check(size_type i, const string &msg) const
    {
        if (i >= data->size())
            throw out_of_range(msg);
    }
    template
    T& Blob::operator[](size_t i){
    	check(i, "subscript out of range"); //    
    	return(*data)[i];
    }
  • のデフォルトでは、インスタンス化されたクラステンプレートのメンバーは、使用時にのみインスタンス化されます.
  • クラステンプレートタイプを使用する場合は、テンプレートの実パラメータを指定する必要がありますが、クラステンプレート自体の役割ドメインでは、実パラメータではなくテンプレート名を直接使用できます.
  • クラステンプレートのメンバーを外部に設定する場合は、クラス名に遭遇した場合にのみクラスの役割ドメインに入ることを示すことを覚えておく必要があります.
  • template
    BlobPtr BlobPtr::operator++(int);

    クラステンプレートと友元
  • クラステンプレートに非テンプレート友元が含まれている場合、友元はすべてのテンプレートインスタンスにアクセスすることを許可される.友元自身がテンプレートである場合、クラスはすべての友元テンプレートインスタンスに権限を与えるか、特定のインスタンスにのみ権限を与えることができます.
  • で友元宣言を行うには、まずテンプレート自体を先に宣言する必要があります.
  • //    , Blob       
    template  class BlobPtr;
    template  class Blob;
    template 
        bool operator==(const Blob&, const Blob&);
    
    template  class Blob {
            //  Blob                  BlobPtr      
            friend class BlobPtr;
            friend bool operator==
                    (const Blob&, const Blob&);
    };
  • はtypedefを定義してインスタンス化されたクラスを参照したり、usingを使用してタイプ別名を宣言したりすることができます.
  • typedef Blob StrBlob;    //      Blob 
    
    template  using twin = pair;   //twin pair   
    twin authors;     //authors   pair

    クラステンプレートのstaticメンバー
  • 各クラステンプレートのインスタンスには独自のstaticメンバーインスタンスがありますが、指定されたタイプについては、staticメンバーインスタンスが共有されます.クラステンプレートのstaticメンバーには定義が1つしかありません.