第二章:C ++の一般的なメカニズムの基礎:データ型のテーブル - 「C ++ジェネリック:STLの原則とアプリケーションが」仕上げの研究ノート

第二章:C ++の一般的なメカニズムの基礎 - データタイプ表

テンプレートクラス2.1の公開データ型のメンバー
クラスの2.1.1データ型のメンバー

  C ++クラスはデータメンバと関数メンバが、また、定義されたデータ型のメンバーではないだけを定義することができます。ジェネリックデータ型の設計では一般的な感謝のクラスのメンバーです。いわゆるクラスのデータ型のメンバは、クラス内の既知のデータ型のtypedefでエイリアスを使用して定義されます。例えば:

typedef long double LDBL 

  このクラステンプレートで定義されたC ++のデータ型に、また、ネストされた型(埋め込み型)として知られています。ネストされたタイプとフィールドメソッドは、クラスのメンバーに属しているので、その後、もちろん、我々は彼らに応じて与えることができますプロパティへのアクセスをしたがって、パブリックプロパティを持つメンバーのこれらのタイプは、公開外部モジュールのクラスタイプの部材を用いてもよいとなります。もちろん、外部モジュールは、公共のメンバーのこれらのタイプによって、テンプレートとクラスの間で機能を実現することができますコラボレーション

template<typename T1, typename T2>
class MyTraits{
public:
    typedef T1 my_Type1;
    typedef T2 my_Type2;
};

int main(int argc, char** argv){
    //类外引用类模板的公有类型成员,与引用静态成员一样。
    //为了区别,需要加上typename关键字
    typename MyTraits<int, double>::my_Type1 t1;
    typename MyTraits<int, double>::my_Type2 t2;
}
2.1.2 typedefの話

  typedefを文字通り定義型、または定義された型を意味します。それはしかし、空中からでないタイプを定義するために、それだけで、既存のタイプ(システムに固有の、ユーザ定義の)名前である別名人々はしばしば、それが時には大きなメリットをもたらすでしょうエイリアスを使用している、同じ理由でエイリアスを使用しています。

  1. 読みやすさを増やします。
    この効果は、エイリアシングの方法でデータの種類にアプリケーション・データ・タイプで説明することができます。
typedef int Phone;
typedef int Age;

//很明显wangxin_P这个变量就是用来存储电话的!
Phone Wangxin_P;
  1. 長くて複雑な型の別名単に名前付き。
/*
一个数组,数组存放的是:
    函数指针:{
        参数:指针函数:{
            参数:空;
            返回值:空;
            }
        返回值:空;
        }
*/
void ( *b[10] )( void(*)() );
//pFunParam是一个函数指针,指向参数为空,返回值为空的函数类型。
typedef void(* pFunParam) ();
//pFunx是一个函数指针,指向参数为别名为pFunParam的类型,返回值为空。
typedef void(*pFunx) (pFunParam);

void (*b[10])(void(*)());
pFunx b[10];
/*
以上两者等价:
声明一个数组b,具有十个元素,元素类型是:
    函数指针:{
        参数:函数指针:{
                参数:空;
                返回值:空;
            }
        返回值:空;
    }
*/
  1. 書き込み、プラットフォームに依存しないコード(クロスプラットフォーム)
    の書き込み、プラットフォームに依存しないコードに比べて最も賞賛のtypedefアプリケーション。これは、プログラミング別名クラス名を使用して行われ、真のタイプのエイリアス名がtypedefのコードを実行使用してインターネットに依存して決定されるように、例えば、32ビットの符号なし整数変数UINT32別名プログラムは、定義されています。オペレーティング・プラットフォームを変更するときに、他の言葉では、ソースコードを変更する必要はありません!
//平台A
typedef int UINT32;
//平台B
typedef unsigned int UINT32;
2.2埋め込まれたデータ型と派生データ型テーブル

  使いやすさのために、テンプレートクラスであろうフォームテーブルデータタイプ内のtypedef定義を使用して、すべての公衆データタイプ、及びテンプレートの正面に位置。データテーブルのこのタイプは、クラステンプレート内に存在する、いわゆる組み込みデータ型テーブル
  テンプレートパラメータからのデータ型の限られた数の完全な使用を取得するには、テンプレートは、多くの場合、公共の外のメンバーによってテンプレートに渡されたパラメータの型の定義に加えて、遠くできるだけテンプレートパラメータから取得したリソースのこれらのタイプを使用し、また彼らを置きます派生型は、まとめて公衆のメンバーとして定義します。

//有人把这种数据类型表形象地称为类型榨取机,或者类型萃取机
template<typename T>
struct map{
    typedef T value_type;
    typedef T& reference;
    typedef T* pointer;
}
表2.3データ型
2.3.1データ型のテーブルコンセプト

  すべてのメンバーが埋め込まれたデータ種別テーブルに対する公衆データ・タイプである場合、クラステンプレートで、クラステンプレートと呼ばれる独立したデータタイプテーブルと呼ばれる、データ型テーブル
  そのようなテーブルは、典型的にするために使用されるテンプレートタイプテーブルを調節しますあなたは、少なくとも2つのパラメータを使用しなければならないプロジェクトテンプレートを必要とし、これら2つのパラメータと参照型アウトのタイプのために価値を提供しなければならないプロジェクトがある場合は、この要件を説明するために、プロジェクトリーダーは、スタンドアロンのデータとして書き込むことができますタイプテーブル。

template<typename T, typename U>
class TypeTb1{
public:
    typedef T value_type1;
    typedef T& reference1;
    
    typedef U value_type2;
    typedef U& reference2;
};

  そしてされるように設計された他の人のクラステンプレート尋ねる継承された独立したタイプのテーブルからを。だから、継承TypeTb1クラスはTypeTb1同じタイプのテーブルを持っています。簡単に言えば、これは独立したテーブル型インタフェースの一種であるインターフェイスのタイプ

template<typename T, typename U>
class A:public TypeTb1<T, U>
{
    //类A的设计内容
};

//例如STL使用binary类模板描述了它对标准二元函数(有两个形参的函数)的要求
template<class _A1, class _A2, class _R>
struct binary
{
    typedef _A1 Arg1;
    typedef _A2 Arg2;
    typedef _R Rtn;
}
2.3.2アプリケーションデータテーブルの種類
template<typename T>
class Num:public TypeTb1<T>
{
    //继承了TypeTb1
};

//普通测试函数,可以发布Num<int>的数据类型表
//缺点,重用性差,每次都需要修改模板参数
//事实证明编译器已经只能到可以省略显式调用数据类型表时的typename关键字了
void Tfunction(Num<int>::value_type x,
                Num<int>::reference y,
                Num<int>::pointer z){
    cout<<"x="<<x<<endl;
    cout<<"y=&x="<<y<<endl;
    cout<<"*z="<<z<<endl;
}
//测试函数模板,注意:
//1.Num不是类型,Num<int>才是类型。
//2.需要使用关键字typename。隐式调用需要关键字。
template<typename T>
void Tfunc(typename T::value_type x,
            typename T::reference y,
            typename T::pointer z){
    cout<<"x="<<x<<endl;
    cout<<"y=&x="<<y<<endl;
    cout<<"*z="<<z<<endl;   
}


int main(int argc, char** argv){
    //显式调用时,typename关键字可以省略
    typename Num<int>::value_type a = 100;
    //调用普通测试函数
    Tfunction(a, a, &a);
    //调用测试函数模板,类型为Num<int>,而不是Num,Num类模板。
    Tfunc<Num<int>>(a, a, &a);
    
    return 0;
}

2.4レイドデータタイプテーブル

  よく知られている、データタイプテーブルは、テンプレートクラスの一種であり、データ型テーブルは特許文献クラスによって形成される型テーブルのテンプレートです。テーブルの種類を専門と役割の一つは達成することにある異なるインターフェース統一同じビジネスロジックを

class Test1{
public:
    char compute(int x, double y){
        return x;
    }
};
class Test2{
public:
    int compute(double x, double y){
        return x;
    }
};
//Test1和Test2两个类的逻辑相同,只是接口不同
//出于代码重用的方式,我们可以写成一个类模板
template<typename Arg1, typename Arg2, typename Ret>
class Test{
public:
    Ret compute(Arg1 x, Arg2 y){
        return x;
    }
};
//这种方法的缺点就是我们需要在声明的时候给出三个模板参数
Test<int, double, char> t1;

//但是如果只是区分两个类,不考虑其他参数类型情况,我们不必如此麻烦
//我们可以使用一套统一的数据类型表,作为类的接口
template<typename T>
class TypeTb1{
    typedef int ret_type;   //返回值数据类型
    typedef int par1_type;  //参数1的数据类型
    typedef int par2_type;  //参数2的数据类型
};
//声明两个空类,作为两个标识符,注意Test1和Test2都是类型
class Test1;
class Test2;
//特例化数据类型表,当模板参数为Test1类时
template<>
class TypeTb1<Test1>{
    typedef char ret_type;  //返回值数据类型
    typedef int par1_type;  //参数1的数据类型
    typedef double par2_type;   //参数2的数据类型
};
template<>
class TypeTb1<Test2>{
    typedef int ret_type;   //返回值数据类型
    typedef double par1_type;   //参数1的数据类型
    typedef double par2_type;   //参数2的数据类型
};
//使用统一数据类型表作为接口,声明的类模板
template<typename T>
class Test{
public:
    //当模板参数为Test1或者Test2时,生成特例化类型表
    //所以compute函数的参数与返回值类型跟着改变
    typename TypeTb1<T>::ret_type compute(
        typename TypeTb1<T>::par1_type x, 
        typename TypeTb1<T>::par2_type y){
        return x;   
    }
}
//成功通过一个模板参数区分了两个类
Test<Test1> t1;
Test<Test2> t2;
表2.5 STL形質

  形質が実際STLに特に適用文献データ種別テーブルであり、データ型テーブルです。彼は独創的だったので、しかし、非常にトレイトのスキルと呼ばれ、尊敬。

  1. バックグラウンドアプリケーションを
      有するSTLに有しているの位置を示すデータオブジェクト関数は、呼び出される(イテレータ)イテレータを、彼らはそれによってテンプレートパラメータにわたって外側に設けること、ほとんどテンプレートクラスであり、テンプレートに埋め込まれたデータを含むタイプのテーブルデータタイプ派生型のユーザーのエイリアス。これらのコードは、一般的にテンプレートクラスを以下のイテレータ
template<typename T>
class Iterator_1{
public:
    typedef T value_type;
    typedef value_type* pointer;
    typedef value_type& reference;
//其余代码···
}
//Iterator_2, Iterator_3 ......
  1. 使用レイドテンプレートポインタテーブルデータ型が
      よく知られており、C / C ++ポインタは、データの位置を示し、従ってイテレータのカテゴリに属するので、インタフェースの種類を統一するために、次にポインタが外側データ・タイプを提供することができなければならないために使用されます。しかし、残念ながら、ポインタはC / C ++がある元の型いないクラスまたはクラステンプレート、何の組み込みデータ型のテーブルが存在しないことができ、STLの要件を満たすために他の方法を考えることが必要です。
      データは外向きポインタ型を提供することができない理由は、それが理由クラスではないが、データ種別テーブルの確立のための場所がない、ファーストクラスのポインタ・データ・タイプを持つテンプレートは、ポインタ・テーブルを保持することができます。明らかに、クラスT *テンプレートのこのタイプを見つけるアプリケーションのために、これは次の形式である必要があり、特別なテンプレート
//基础模板
template<typename T>
struct Traits{
    //空表
}
//指针的特化模板
template<typename T>
struct Traits<T*>{
    typedef T value_type;
    typedef value_type* pointer;
    typedef value_type& reference;
}
//Traits表特别体现了数据类型表的“类型压榨”能力
//即它不仅能把用户经由模板参数传递来的一个数据类型的所有衍生类型都能提取出来,
//而且还可以把衍生类型的原生数据类型压榨出来。
Traits<double*>::value_type t1 = 100;
cout<<t1<<endl;
  1. 同様のクラステンプレートの概要埋め込みデータタイプテーブルは、形成するために統一されたインタフェースを
      解決するために、特殊なデータ・タイプ・テーブルを使用し、データ型テーブルのネイティブ型問題が、各イテレータデータテーブルの種類や各イテレータクラスの分散が助長されていません管理。だから希望があるものと同じタイプのテーブルの(ここではイテレータ)概要表のデータ型が。
      だから、STLの設計者は、空のテーブルの上の特徴、基本的なテンプレートを見ました。データは、コンテンツの各イテレータテンプレート型テーブルの後にコピーされている場合は、この空のテーブルにほとんど変化があなたのために非常に良いではありません!総リストイテレータ型テーブルであるトレイト。トレイト空のテーブルには、次のようになりそう。
//这里的模板参数T的实参将来都是各个迭代器类以及T*。
template<typename T>
struct Traits{
    //因为编译器不认识带有域分隔符::的类型,因此这里需要使用关键字typename
    typedef typename T::value_type value_type;  //隐式调用数据类型成员
    typedef typename T::pointer pointer;
    typedef typename T::reference reference;
}
//指针特化模板与之前一样。
//测试如下,由此可见数据类型表都变成了Traits,统一了接口
Traits<Iterator_1<int>>::value_type t1 = 100;
Traits<Iterator_2<double>>::value_type t2 = 9.23;
Traits<double*>::value_type t3 = 3.33;

おすすめ

転載: www.cnblogs.com/azhao/p/11881255.html
おすすめ