コメントが言及したように、これはCuriously Recurring Template Patternとして知られています。このパターンは、多くの場合、仮想関数に似たメカニズムを提供するために実装されますが、コンパイル時に実装されます (静的ポリモーフィズム)。たとえばRecursiveASTVistor<T>
、次のことを行うメソッドが含まれる場合があります。
...
//using T = MyRecursiveASTVisitor; for your specific case
T *concrete_visitor = static_cast<T*>(this);
concrete_visitor->VisitStmt(something);
VisitStmt
がクラスで定義されている場合MyRecursiveASTVisitor
、そのメソッドが呼び出されます。それ以外の場合は、 によって提供される基本定義が呼び出されRecursiveASTVistor
ます。クラス階層外の呼び出し元も、この静的ポリモーフィズムを利用できます。
何が起こっているのかをよりよく理解するのに役立つ短い例を次に示します。
#include <iostream>
template <class T>
struct Base {
void foo() {
T *concrete = static_cast<T*>(this);
concrete->foo();
};
void bar() {std::cout << "Base" << std::endl; }
};
struct Derived : public Base<Derived> {
void foo() {std::cout << "Derived" << std::endl;}
};
int main() {
Base<Derived> b;
b.foo();
b.bar();
}
出力
Derived
Base
編集:追加の質問に答えるには:
また、行に Rewrite(R) と書くと
MyRecursiveASTVisitor(Rewriter &R) : Rewrite(R) { }
、値 R が変数 Rewrite に代入されますか? コードのどこにもクラス Rewrite が定義されていません。「:」演算子は、クラスからの継承以外に使用されますか?
Rewrite
はクラスのメンバー変数でありMyRecursiveASTVisitor
、タイプ のオブジェクトへの参照Rewriter
です。:
演算子はコンストラクターの定義で使用され、メンバー初期化子リストを示します。この場合、Rewrite
渡された引数で変数を初期化するだけR
です。明確にするMyRecursiveASTVisitor(Rewriter &R) : Rewrite(R) { }
ために、はクラスのコンストラクター定義であり、クラス定義MyRecursiveASTVisitor
ではありません。