私のシステムは非常に「重い」(大量のコード) ですが、非常に高速で機能が豊富です (クロスプラットフォーム C++)。あなたがデザインをどこまでやりたいかはわかりませんが、私が行ったことの最大の部分は次のとおりです。
DatumState- 「型」の「列挙型」に加えて、を含むすべてのプリミティブ型の「結合」であるネイティブ値を保持するクラスvoid*。このクラスはすべての型から切り離されており、ネイティブ/プリミティブ型、および「参照先」void*型に使用できます。" " は " " と " " のコンテキストenumも持つため、このクラスは a (または何らかのプリミティブ型) を「完全に含む」、または「参照しているが所有していない」a (または何らかのプリミティブ型) として提示できます。(私は実際に " "、" "、および " " コンテキストを持っているので、value、reference-that-cannot-be-null を論理的に格納できます。VALUE_OFREF_TOfloatfloatVALUE_OFREF_TOPTR_TO
Datum- 完全に を含むクラスですDatumStateが、インターフェイスを拡張して、さまざまな「既知の」型 ( MyDate、MyColor、MyFileNameなど) に対応します。これらの既知の型は、実際にはメンバーのvoid*内部に格納されます。DatumStateただし、 の " enum" 部分にはDatumState" VALUE_OF" と " " のコンテキストがあるため、" " または " "REF_TOを表すことができます。pointer-to-MyDatevalue-of-MyDate
DatumStateHandle- (既知の) 型 ( 、 、 など) でパラメータ化されたヘルパー テンプレート クラスMyDate。MyColorこれは、既知の型から状態を抽出するためにMyFileNameによって使用されるアクセサーです。Datumデフォルトの実装はほとんどのクラスで機能しますが、アクセスに関する特定のセマンティクスを持つクラスは、このテンプレート クラスの 1 つ以上のメンバー関数の特定のテンプレート パラメータ化/実装をオーバーライドするだけです。
Macros, helper functions, and some other supporting stuffDatum- /へのよく知られた型の「追加」を簡単にするために、Variantロジックをいくつかのマクロに集中させ、演算子のオーバーロードなどのサポート関数を提供し、コードに他の規則を確立すると便利であることがわかりました。
この実装の「副作用」として、参照と値のセマンティクス、すべての型での「null」のオプション、すべての型での異種コンテナーのサポートなど、多くの利点が得られました。
たとえば、一連の整数を作成してインデックスを付けることができます。
int my_ints[10];
Datum d(my_ints, 10/*count*/);
for(long i = 0; i < d.count(); ++i)
{
d[i] = i;
}
同様に、一部のデータ型は、文字列または列挙型によってインデックス付けされます。
MyDate my_date = MyDate::GetDateToday();
Datum d(my_date);
cout << d["DAY_OF_WEEK"] << endl;
cout << d[MyDate::DAY_OF_WEEK] << endl; // alternative
アイテムのセット (ネイティブ) またはセットのDatumアイテム (各アイテムをラップ) を格納できます。どちらの場合でも、再帰的に「アンラップ」できます。
MyDate my_dates[10];
Datum d(my_dates, 10/*count*/);
for(long i = 0; i < d.count(); ++i)
{
cout << d[i][MyDate::DAY_OF_WEEK] << endl;
}
REF_TO私の " " と " " のセマンティクスはやり過ぎだと主張する人もいるかもしれませんVALUE_OFが、それらは「セットのアンラップ」には不可欠でした。
私はこの " Variant" ことを 9 つの異なるデザインで行いました。私の現在のものは「最も重い」(ほとんどのコード) ですが、私が一番気に入ったもの (オブジェクトのフットプリントがかなり小さく、ほぼ最速) であり、廃止予定です私の使用のための他の8つのデザイン。
私の設計の「欠点」は次のとおりです。
- オブジェクトは
static_cast<>()a からアクセスされますvoid*
(タイプ セーフでかなり高速ですが、間接化が必要です。ただし、副作用として、設計により " null" の格納がサポートされます)。
Datumよく知られている型がインターフェイスを介して公開されるため、コンパイルに時間がかかります (ただし、DatumStateよく知られている型の API が必要ない場合は使用できます)。
デザインに関係なく、次のことをお勧めします。
「 」などを使用して、「値」とは別に「タイプenum」を伝えます。(それらを 1 つの " " またはビット パッキングを使用して圧縮できることは知っていますが、これはアクセスが遅く、新しい型が導入されると維持するのが非常に難しくなります。)int
型固有の (オーバーライド) 処理のメカニズムを使用して、操作を集中化するためにテンプレートまたは何かに依存します (重要な型を処理する場合)。
ゲームの名前は、「新しいタイプを追加するときのメンテナンスの簡素化」です(または、少なくとも、私にとってはそうでした)。優れたターム ペーパーのように、システムを維持するために必要なコードを常に削除する (たとえば、新しい型を適応させるために必要な労力を最小限に抑える) ため、機能を維持または向上させるために、書き直し、書き直し、書き直しを行うことは非常に良い考えです。既存のインフラストラクチャに)。Variant
幸運を!