C ++テンプレートは、型を引数として取ることがよく知られていますが、他の型のデータに対してもパラメーター化することができます。たとえば、次に示すように、整数を使用してクラスをテンプレート化できます。
template <typename T, unsigned int N> class Array {
private:
T array[N];
public:
/* ... */
};
テンプレートは、ポインターが特定の基準を満たしている限り、ポインターを介してパラメーター化することもできます(たとえば、コンパイル時に決定できる何かのアドレスに評価する必要があります)。たとえば、これは完全に合法です。
template <int* Pointer> class ThisIsLegal {
public:
void doSomething() {
*Pointer = 137;
}
};
コードでは、テンプレートはクラスメンバーへのポインタを介してパラメータ化されています。クラスメンバーへのポインタは、あるオブジェクトを間接的に参照するという点でポインタに似ています。ただし、オブジェクトを指す代わりに、クラス内のフィールドを指します。アイデアは、あるオブジェクトに関連するクラスメンバーへのポインタを逆参照して、クラスからそのフィールドを選択できるということです。クラスメンバーへのポインタの簡単な例を次に示します。
struct MyStruct {
int x, y;
};
int main() {
MyStruct ms;
ms.x = 137;
ms.y = 42;
int MyStruct::* ptr; // Declare a pointer to a class member.
ptr = &MyStruct::x; // Now points to the field 'x'
ms.*ptr = 0; // Set the 'x' field of ms to be zero.
}
クラスメンバーへのポインタを宣言するための構文は次のとおりです。
Type ContainingClass::* pointerName;
したがって、上記のコードでは、「クラス内int MyStruct::* ptr
へのポインタ」を意味します。int
MyStruct
投稿したコードでは、テンプレート宣言は次のようになっています。
template <
class PropObject,
class PropType,
PropType PropObject::* Prop
>
class PropReader
これが何を意味するのか見てみましょう。プロパティが読み取られる最初の2つのテンプレート引数オブジェクト、およびそのプロパティのタイプ。 "テンプレートへの最後の引数は、タイプのフィールドでa内を指すPropType
という名前のクラスメンバーへのポインタです。たとえば、次のようにこのテンプレートをインスタンス化できます。Prop
PropObject
PropType
MyStruct
PropReader<MyStruct, int, &MyStruct::x> myPropReader;
それでは、残りのコードが何をするか見てみましょう。このクラステンプレートの本文はここに転載されています:
void print(Object& o)
{
PropObject& po = static_cast<PropObject &>(o);
PropType& t = po.*Prop;
cout << t << "\n";
}
これのいくつかはかなり簡単に読むことができます。この関数のパラメーターはObject
名前付きのへの参照o
であり、最後の行はいくつかのフィールドを出力します。これらの2行は注意が必要です。
PropObject& po = static_cast<PropObject &>(o);
PropType& t = po.*Prop;
o
この最初の行は、「引数を型の参照にキャストしてみてくださいPropObject
。アイデアObject
は、多くの異なるオブジェクトの基本クラスであるということです。関数のパラメーターは単なるプレーンです。Object
、そしてこのキャストはそれを適切なタイプのものに変換しようとします(PropObject
オブジェクトのタイプが何であるかを示すテンプレート引数であることを思い出してください)。これはstatic_cast
、変換が定義されていない場合(たとえば、インスタンス化しようとした場合)にを使用するためです。テンプレートがint
またはvector<string>
)の場合、コードはコンパイルされません。それ以外の場合、コードはキャストが安全であると信頼しPropObject
、パラメーターが参照するものへの型の参照を取得します。
最後に、最後の行は
PropType& t = po.*Prop;
これは、前述のクラスメンバーへのポインター逆参照構文を使用して、「Prop
(テンプレート引数)が指すフィールドを選択し、。という名前のフィールドへの参照を格納しますt
。
つまり、テンプレート
- オブジェクトのタイプを尋ねます。
- そのオブジェクトのフィールドのタイプを尋ねます。
- そのオブジェクトのフィールドへのポインタを要求します。
print
オブジェクトを指定してそのフィールドを出力しようとする関数を提供します。
ふぅ!それはトリッキーでした!お役に立てれば!