は、我々はenumeredタイプ持っている、と仮定しよう(列挙型変数
template<DataType T>
struct TypeTraits {};
template<>
struct TypeTraits<INT> { typedef int T; };
template<>
struct TypeTraits<DOUBLE> { typedef double T; };
と操作を表し、いくつかのテンプレートがありません醜いボイドポインタやC型の型キャストを気にする):
struct Operation {
DataType rettype;
Operation(DataType rettype) : rettype(rettype);
virtual void* compute();
};
template<DataType RetType>
class Constant : public Operation {
typedef typename TypeTraits<RetType>::T RType;
RType val;
Constant(RType val) : val(val), Operation(RetType) {};
virtual void* compute(){ return &val; }
};
template<DataType T1, DataType T2, DataType RetType>
class Add : public Operation {
typedef typename TypeTraits<RetType>::T1 T1Type;
typedef typename TypeTraits<RetType>::T2 T2Type;
typedef typename TypeTraits<RetType>::RetType RType;
RType val;
Operation *c1, *c2;
Add(Operation *c1, Operation *c2) : c1(c1), c2(c2), Operation(RetType) {};
virtual void* compute(){
T1Type *a = (T1Type *)c1->compute();
T2Type *b = (T2Type *)c2->compute();
val = *a + *b;
return &val;
}
};
抽象的なツリー表現:
class AbstractNode {
enum Type { ADD, INT_CONSTANT, DOUBLE_CONSTANT };
Type type;
int intval;
double doubleval;
child1 *AbstractNode;
child2 *AbstractNode;
}
入力からシリアル化された抽象ツリーを読み込んで、操作ツリーに変換し、結果を計算します。
は、我々のような何かを書きたい:add_types_resolver
は、操作の引数の型に基づいて、追加操作の戻り値の型を指定するものです
algebrator(Operation *op){
if(op->type == AbstractNode::INT_CONSTANT)
return new Constant<INT>(op->intval);
else if(op->type == AbstractNode::DOUBLE_CONSTANT)
return new Constant<DOUBLE>(op->doubleval);
else {
Operation *c1 = algebrator(op->child1),
*c2 = algebrator(op->child2);
DataType rettype = add_types_resolver(c1->rettype, c2->rettype);
return new Add<c1->rettype, c2->rettype, rettype>(c1, c2);
}
}
。
私たちはもちろん失敗し、コンパイラは私たちの顔を打つでしょう。変数をテンプレート変数として使用することはできません!これは、テンプレートをインスタンス化するために必要なすべての情報が合併中に利用可能でなければならないからです!
今、質問です。
if-elseやswitch-case文をたくさん書く以外の方法はありますか?コンパイル中にすべてのケースを拡張するためにコンパイラーに何らかの方法で問い合わせることはできませんか?テンプレートはenumによってパラメータ化されているので、そのようなプロセスは有限であるという保証があります。
そして、「私はすべての例が台無しになっていると思う」といったような回答を書いてはいけません。テンプレートを変数に渡す方法があるかどうかを知りたいだけで、有限の小さなセットからのものであることがわかります。
全体的に見れば過度のように思えるかもしれませんが、私は本当に不思議なことに、どのようにクラスをインスタンス化できますか?
:ここTypetraitsの私の同等がどのように見えるかです。テンプレートは、実行時の値ではなく、型とコンパイル時定数でパラメータ化されます。しかし、それはあなたがすでにそれを認識しているように聞こえます。 –
int型のイディオムを使用してテンプレートのコンパイル時の型を生成できますが、それは良い考えかどうかはまったく別の問題です。 – AJG85
動的ルックアップコードをプログラムの1つのコーナーに分解して、あまりノイズを発生させずに使用できるようにするのは非常に難しいことではありません。 –