[解決済み】CRTP(Curiously Recurring Template Pattern)とは何ですか?)
質問
について、本を参照することなく、どなたか良い説明をお願いします。
CRTP
をコード例付きで教えてください。
どのように解決するのですか?
要するに、CRTPとは、あるクラスが
A
のテンプレート特化である基底クラスがあります。
A
そのものです。例
template <class T>
class X{...};
class A : public X<A> {...};
それは は 不思議と繰り返されるんですよね(笑)。
さて、これで何がわかるでしょうか。これは実際に
X
テンプレートは、その特殊化のための基本クラスとなる能力を備えています。
例えば、次のような汎用シングルトン・クラス(簡易版)を作ることができます。
template <class ActualClass>
class Singleton
{
public:
static ActualClass& GetInstance()
{
if(p == nullptr)
p = new ActualClass;
return *p;
}
protected:
static ActualClass* p;
private:
Singleton(){}
Singleton(Singleton const &);
Singleton& operator = (Singleton const &);
};
template <class T>
T* Singleton<T>::p = nullptr;
さて、任意のクラスを作るために
A
をシングルトン化するには、次のようにします。
class A: public Singleton<A>
{
//Rest of functionality for class A
};
というわけで、お分かりいただけたでしょうか?シングルトンテンプレートは、任意の型に対するその特殊化を想定しています。
X
から継承されます。
singleton<X>
を含む、そのすべての (public, protected) メンバにアクセスできるようになります。
GetInstance
! CRTPには、他にも便利な使い方がある。例えば、あなたのクラスに現在存在する全てのインスタンスをカウントしたいが、このロジックを別のテンプレートにカプセル化したい場合(具象クラスのアイデアは非常にシンプルです - 静的変数を持って、ctorsで増分し、dtorsで減分します)。練習としてやってみてください。
もう一つ、Boostの便利な例を紹介しよう(どのように実装されたかはわからないが、CRTPでも可能)。
演算子
<
を使用し、自動的に演算子
==
を使用します。
というようなことができます。
template<class Derived>
class Equality
{
};
template <class Derived>
bool operator == (Equality<Derived> const& op1, Equality<Derived> const & op2)
{
Derived const& d1 = static_cast<Derived const&>(op1);//you assume this works
//because you know that the dynamic type will actually be your template parameter.
//wonderful, isn't it?
Derived const& d2 = static_cast<Derived const&>(op2);
return !(d1 < d2) && !(d2 < d1);//assuming derived has operator <
}
これで、次のように使うことができます。
struct Apple:public Equality<Apple>
{
int size;
};
bool operator < (Apple const & a1, Apple const& a2)
{
return a1.size < a2.size;
}
今、あなたは明示的に演算子を提供していない
==
に対して
Apple
? しかし、あなたはそれを持っている!?と書くことができます。
int main()
{
Apple a1;
Apple a2;
a1.size = 10;
a2.size = 10;
if(a1 == a2) //the compiler won't complain!
{
}
}
これは、演算子を書くだけなら書く量が減るように見えるかもしれません。
==
に対して
Apple
が、想像してみてください。
Equality
を提供するだけでなく
==
しかし
>
,
>=
,
<=
などです。そして、これらの定義を
マルチプル
クラスを作成し、コードを再利用することができます。
CRTPは素晴らしいものです :) HTH
関連
-
[解決済み】 unsigned int vs. size_t
-
[解決済み] error: 'if' の前に unqualified-id を期待した。
-
[解決済み] 変数サイズのオブジェクトが初期化されないことがある c++
-
[解決済み] スタックアロケーションにより初期化されていない値が作成された
-
[解決済み] explicit キーワードの意味は?
-
[解決済み] ルール・オブ・スリーとは?
-
[解決済み] 要素ごとの加算は、結合ループよりも分離ループの方がはるかに高速なのはなぜですか?
-
[解決済み] コピーアンドスワップ慣用句とは?
-
[解決済み] template "と "typename "キーワードはどこに、なぜ入れなければならないのですか?
-
[解決済み】C/C++の"-->"演算子とは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】 unsigned int vs. size_t
-
[解決済み】抽象クラス型の無効なnew-expression
-
[解決済み】「corrupted size vs. prev_size」glibc エラーを理解する。
-
[解決済み】fpermissiveフラグは何をするのですか?
-
[解決済み】エラー:strcpyがこのスコープで宣言されていない
-
[解決済み】Visual Studio 2013および2015でC++コンパイラーエラーC2280「削除された関数を参照しようとした」が発生する
-
[解決済み】クラステンプレートの使用にはテンプレート引数リストが必要です
-
[解決済み】エラー:不完全な型へのメンバーアクセス:前方宣言の
-
[解決済み】C++ - ステートメントがオーバーロードされた関数のアドレスを解決できない。
-
[解決済み】デバッグアサーションに失敗しました