さまざまなメンバーを持つデータ構造の問題を解決するには多くの方法があり、どれが最適かは、それがどのように使用されるかによって大きく異なります。
最も明白なのは、継承を使用することです。基本クラスからすべての可能性を導き出します。
struct base_struct {
int id;
std::string name;
};
list<base_struct*> some_list;
struct some_struct : public base_struct {
double metricA;
};
struct some_other_struct : public base_struct {
int metricB;
};
base_struct *s1 = new some_struct;
s1->id = 1;
// etc
base_struct *s2 = new some__other_struct;
s2->id = 2;
// etc
some_list.push_back(s1);
some_list.push_back(s2);
注意が必要な点は、要素を元に戻すときに、大文字と小文字を適切に区別する必要があることです。 dynamic_cast
タイプセーフな方法でこれを行うことができます:
some_struct* ss = dynamic_cast<some_struct*>(some_list.front());
次を使用して、キャストする前に名前を照会できますtype_info
。
typeid(*some_list.front()).name();
これらはどちらも RTTI でビルドする必要があることに注意してください。通常は問題ありませんが、RTTI にはパフォーマンス コストがかかり、特にテンプレートが広範囲に使用されている場合はメモリ フットプリントが肥大化する可能性があるため、常にそうとは限りません。
以前のプロジェクトでは、 boost anyを使用して同様の処理を行いました。の利点any
は、互いに派生していない型を混在させることができることです。振り返ってみると、型チェックがそれまで延期されているため、コードが実行時に失敗する可能性が少し高くなったため、もう一度やり直すかどうかはわかりません。(これはdynamic_cast
アプローチにも当てはまります。
古き良き C の時代には、この同じ問題を次のように解決しましたunion
。
struct base_struct {
int id;
std::string name;
union { // metricA and metricB share memory and only one is ever valid
double metricA;
int metricB;
};
};
繰り返しになりますが、自分で正しいタイプであることを確認する必要があるという問題があります。
STL が登場する前の時代、多くのコンテナ システムは を取得するように記述されていたためvoid*
、ユーザーはいつキャストするかを知る必要がありました。理論的には、そうすることができlist<void*>
ますが、型を照会する方法はありません。
編集:絶対にメソッドを使用しないでくださいvoid*
!