1.テンプレートを定義します
16.1.1関数テンプレート
タイプごとに新しい関数を定義する代わりに、一般的な関数テンプレートを定義できます
できるよ:
#include <memory>
#include <cstring>
template <typename T>
int compire(const T &v1,const T &v2)
{
if(v1<v2)
{
return -1;
}
if(v1>v2)
{
return 1;
}
return 0;
}
int main()
{
printf("%d\n",compire(1,2));
return 0;
}
クラステンプレート
テンプレートにTというパラメータがあることがわかりました
//
// Created by root on 20-2-27.
//
#ifndef TEST_TEMPLATE_H
#define TEST_TEMPLATE_H
//
// Created by root on 20-2-27.
//
#include <vector>
template <typename T>class BlobA{
public:
typedef T value_type;
typedef typename std::vector<T>::size_type size_type;
BlobA()
{
}
int add(T a,T b)
{
return a+b;
}
};
#endif //TEST_TEMPLATE_H
呼び出し場所
#include <memory>
#include <cstring>
#include <iostream>
#include "template.h"
int main()
{
BlobA<int> a;
std::cout<<a.add(1,2)<<std::endl;
return 0;
}
クラステンプレートのインスタンス化:
クラステンプレートを使用する場合、テンプレートパラメータにバインドされているテンプレート引数のリストを表示するために追加情報を提供する必要があることを何度も見てきました。コンパイラは、これらのテンプレート引数を使用して、これらの特定のクラスをインスタンス化します。
ここで本を見るのはこのように書かれたデモであり、私の疑問を引き起こしました
#include <memory>
#include <cstring>
#include <iostream>
#include "template.h"
int main()
{
BlobA<int> a = {0,1,2};
std::cout<<a.add(1,2)<<std::endl;
return 0;
}
クラスを{0,1,2}に初期化できる理由
元のコンストラクターはここでオーバーロードされます
//
// Created by root on 20-2-27.
//
#ifndef TEST_TEMPLATE_H
#define TEST_TEMPLATE_H
//
// Created by root on 20-2-27.
//
#include <vector>
template <typename T>class BlobA{
public:
typedef T value_type;
typedef typename std::vector<T>::size_type size_type;
BlobA()
{
}
BlobA(std::initializer_list<T> il)
{
}
int add(T a,T b)
{
return a+b;
}
};
#endif //TEST_TEMPLATE_H
カスタムタイプにinitializer_listを使用する方法について簡単に説明します。
C ++ 11は、ユーザーがカスタムタイプ(一般にクラスと呼ばれる)で初期化リストを使用するためのメソッドも提供します。
インスタンス化されたクラスを見てみましょう
BlobA(std :: initializer_list il)
{
for (auto a : il)
{
std::cout<<a<<std::endl;
}
}
結果は0,1,2,3です
私たちは本の裏を読み続けます
スマートポインター使用テンプレート
std::shared_ptr<BlobA<int>> data;
dataはshared_ptrのインスタンスであり、このshared_ptrはタイプTのオブジェクトのベクトルインスタンスを保持します
1.テンプレートを定義します
16.1.1関数テンプレート
タイプごとに新しい関数を定義する代わりに、一般的な関数テンプレートを定義できます
できるよ:
#include <memory>
#include <cstring>
template <typename T>
int compire(const T &v1,const T &v2)
{
if(v1<v2)
{
return -1;
}
if(v1>v2)
{
return 1;
}
return 0;
}
int main()
{
printf("%d\n",compire(1,2));
return 0;
}
クラステンプレート
テンプレートにTというパラメータがあることがわかりました
//
// Created by root on 20-2-27.
//
#ifndef TEST_TEMPLATE_H
#define TEST_TEMPLATE_H
//
// Created by root on 20-2-27.
//
#include <vector>
template <typename T>class BlobA{
public:
typedef T value_type;
typedef typename std::vector<T>::size_type size_type;
BlobA()
{
}
int add(T a,T b)
{
return a+b;
}
};
#endif //TEST_TEMPLATE_H
呼び出し場所
#include <memory>
#include <cstring>
#include <iostream>
#include "template.h"
int main()
{
BlobA<int> a;
std::cout<<a.add(1,2)<<std::endl;
return 0;
}
クラステンプレートのインスタンス化:
クラステンプレートを使用する場合、テンプレートパラメータにバインドされているテンプレート引数のリストを表示するために追加情報を提供する必要があることを何度も見てきました。コンパイラは、これらのテンプレート引数を使用して、これらの特定のクラスをインスタンス化します。
ここで本を見るのはこのように書かれたデモであり、私の疑問を引き起こしました
#include <memory>
#include <cstring>
#include <iostream>
#include "template.h"
int main()
{
BlobA<int> a = {0,1,2};
std::cout<<a.add(1,2)<<std::endl;
return 0;
}
クラスを{0,1,2}に初期化できる理由
元のコンストラクターはここでオーバーロードされます
//
// Created by root on 20-2-27.
//
#ifndef TEST_TEMPLATE_H
#define TEST_TEMPLATE_H
//
// Created by root on 20-2-27.
//
#include <vector>
template <typename T>class BlobA{
public:
typedef T value_type;
typedef typename std::vector<T>::size_type size_type;
BlobA()
{
}
BlobA(std::initializer_list<T> il)
{
}
int add(T a,T b)
{
return a+b;
}
};
#endif //TEST_TEMPLATE_H
カスタムタイプにinitializer_listを使用する方法について簡単に説明します。
C ++ 11は、ユーザーがカスタムタイプ(一般にクラスと呼ばれる)で初期化リストを使用するためのメソッドも提供します。
インスタンス化されたクラスを見てみましょう
BlobA(std :: initializer_list il)
{
for (auto a : il)
{
std::cout<<a<<std::endl;
}
}
結果は0,1,2,3です
私たちは本の裏を読み続けます
スマートポインター使用テンプレート
std::shared_ptr<BlobA<int>> data;
dataはshared_ptrのインスタンスであり、このshared_ptrはタイプTのオブジェクトのベクトルインスタンスを保持します
クラステンプレートのメンバー関数
クラステンプレートの内部と外部の両方でメンバー関数を定義でき、テンプレートで定義されたメンバー関数は、内向的な関数として暗黙的に宣言されます。
テンプレートの外部で定義されたクラステンプレートメンバー関数は、テンプレートで始まる必要があります
いつものように、クラスの外部でメンバー関数を定義するときは、メンバーが属するクラスを指定する必要があります。また、テンプレート生成クラスの名前には、そのテンプレート引数を含める必要があります。メンバー関数を定義するときは、メンバーが属するクラスを指定する必要があります。また、テンプレートから生成されたクラスの名前には、テンプレートの実際のパラメーターが含まれている必要があります。メンバー関数を定義すると、テンプレートは実際には同じテンプレートパラメーターに参加します。メンバー関数の場合、blobに対応するメンバーは次のようになります。
template <typename T>
ret-type Blob<T>::member-name(parm-list)
テンプレートの定義と宣言を2つのファイルに分割することはできません。コンパイル時に特定のクラスが生成されず、呼び出された場合にのみ生成されるため、.ccを含める必要がありますが、これは適切な解決策ではありません。それはまだ.hファイルに書かれている方が良いです
たとえば、1つは.hに配置され、もう1つは.ccに配置されます。
クラステンプレートと別のテンプレート間の友好関係の最も一般的な形式は、インスタンスと友人の間に友好関係を確立することです。
//
// Created by root on 20-2-27.
//
#ifndef TEST_TEMPLATE_H
#define TEST_TEMPLATE_H
#include <vector>
#include <iostream>
// Created by root on 20-2-27.
//
template <typename >class BlobPtr;
template <typename >class Blob;
template <typename T>
bool operator == (const Blob<T>&,const Blob<T>&);
template <typename T>class BlobA{
public:
friend class BlobPtr<T>;
friend bool operator == <T>(const Blob<T>&,const Blob<T>&);
typedef T value_type;
typedef typename std::vector<T>::size_type size_type;
BlobA()
{
}
BlobA(std::initializer_list<T> il)
{
for (auto a : il)
{
std::cout<<a<<std::endl;
}
}
int add(T a,T b);
};
template <typename T>
int BlobA<T>::add(T a, T b) {
return a+b;
}
#endif //TEST_TEMPLATE_H
テンプレートタイプエイリアス
テンプレートタイプの特性、typedef BlobA data2;
別の方法
エイリアスを指定したいのは、インスタンス化されたテンプレートクラスではなく、テンプレートです
template <typename T>using partNo = BlobA<unsigned>;
クラステンプレートの静的メンバー
他のクラスと同様に、クラステンプレートも静的メンバーを宣言できます。
template <typename T>class BlobA{
public:
static std::size_t count(){ return ctr;};
static std::size_t ctr;
private:
};
//初始化
template <typename T>size_t BlobA<T>::ctr = 0;
//使用
int main()
{
std::cout<<partNo<int>::count()<<std::endl;
return 0;
}
クラステンプレートのメンバー関数
クラステンプレートの内部と外部の両方でメンバー関数を定義でき、テンプレートで定義されたメンバー関数は、内向的な関数として暗黙的に宣言されます。
テンプレートの外部で定義されたクラステンプレートメンバー関数は、テンプレートで始まる必要があります
いつものように、クラスの外部でメンバー関数を定義するときは、メンバーが属するクラスを指定する必要があります。また、テンプレート生成クラスの名前には、そのテンプレート引数を含める必要があります。メンバー関数を定義するときは、メンバーが属するクラスを指定する必要があります。また、テンプレートから生成されたクラスの名前には、テンプレートの実際のパラメーターが含まれている必要があります。メンバー関数を定義すると、テンプレートは実際には同じテンプレートパラメーターに参加します。メンバー関数の場合、blobに対応するメンバーは次のようになります。
template <typename T>
ret-type Blob<T>::member-name(parm-list)
テンプレートの定義と宣言を2つのファイルに分割することはできません。コンパイル時に特定のクラスが生成されず、呼び出された場合にのみ生成されるため、.ccを含める必要がありますが、これは適切な解決策ではありません。それはまだ.hファイルに書かれている方が良いです
たとえば、1つは.hに配置され、もう1つは.ccに配置されます。
クラステンプレートと別のテンプレート間の友好関係の最も一般的な形式は、インスタンスと友人の間に友好関係を確立することです。
//
// Created by root on 20-2-27.
//
#ifndef TEST_TEMPLATE_H
#define TEST_TEMPLATE_H
#include <vector>
#include <iostream>
// Created by root on 20-2-27.
//
template <typename >class BlobPtr;
template <typename >class Blob;
template <typename T>
bool operator == (const Blob<T>&,const Blob<T>&);
template <typename T>class BlobA{
public:
friend class BlobPtr<T>;
friend bool operator == <T>(const Blob<T>&,const Blob<T>&);
typedef T value_type;
typedef typename std::vector<T>::size_type size_type;
BlobA()
{
}
BlobA(std::initializer_list<T> il)
{
for (auto a : il)
{
std::cout<<a<<std::endl;
}
}
int add(T a,T b);
};
template <typename T>
int BlobA<T>::add(T a, T b) {
return a+b;
}
#endif //TEST_TEMPLATE_H
テンプレートタイプエイリアス
テンプレートタイプの特性、typedef BlobA data2;
別の方法
エイリアスを指定したいのは、インスタンス化されたテンプレートクラスではなく、テンプレートです
template <typename T>using partNo = BlobA<unsigned>;
クラステンプレートの静的メンバー
他のクラスと同様に、クラステンプレートも静的メンバーを宣言できます。
template <typename T>class BlobA{
public:
static std::size_t count(){ return ctr;};
static std::size_t ctr;
private:
};
//初始化
template <typename T>size_t BlobA<T>::ctr = 0;
//使用
int main()
{
std::cout<<partNo<int>::count()<<std::endl;
return 0;
}