非 POD の性質を持つ C++ クラスのデータ メンバーのオフセットを取得する方法を探しています。
理由は次のとおりです。
HDF5形式でデータを保存したいのですが、これは私の種類の資料 (数値シミュレーション出力) に最も適していると思われますが、おそらく C 指向のライブラリです。私はC++インターフェイスを介してそれを使用したいので、ストレージタイプを次のように宣言する必要があります( hereとhereのドキュメントに従ってください(セクション4.3.2.1.1)):
class example {
public:
double member_a;
int member_b;
} //class example
H5::CompType func_that_creates_example_CompType() {
H5::CompType ct;
ct.insertMember("a", HOFFSET(example, member_a), H5::PredType::NATIVE_DOUBLE);
ct.insertMember("b", HOFFSET(example, member_b), H5::PredType::NATIVE_INT);
return ct;
} //func_that_creates_example_CompType
ここで、HOFFSET は、offsetof を使用する HDF 固有のマクロです。
問題はもちろん、example-class がもう少し機能的になるとすぐに、もはや POD タイプではなくなるため、offsetof を使用すると未定義の結果が生じることです。
私が考えることができる唯一の回避策は、最初に保存したいデータをより単純な構造体にエクスポートしてから、それを HDF に渡すことです。ただし、これにはデータのコピーが含まれます。これはまさに HDF が回避しようとしているものです (そして、ライブラリがオブジェクトに到達してデータをファイルに保存できるようにするこの CompType がある理由)。
だから、もっといいアイデアがあればいいなと思っていました。理想的には、この問題の移植可能な回避策を探していますが、それが不足している場合でも、GCC を使用して x86 および x86_64 で動作するアイデアを教えていただければ幸いです。
----- 後で追加: -----
Greg Hewgill は、データを単純な構造体に格納し、それを継承して実際のクラスを構築することを以下に提案しました。特に HDF の場合、実際には機能しない可能性があると思います。上記よりも複雑な使用シナリオ:
class base_pod {
public:
double member_a;
int member_b;
}; //class base_pod
class derived_non_pod : private base_pod {
public:
//the following method is only virtual to illustrate the problem
virtual double get_member_a() {return member_a; }
}; //class derived_non_pod
class that_uses_derived_non_pod {
public:
void whatever();
private:
derived_non_pod member_c;
}; //class that_uses_derived_non_pod
さて、クラス that_uses_derived_non_pod のインスタンスを格納するとき、あたかも base_pod を member_c として持っているかのように、そのメモリ レイアウトを記述することはできません。派生した_non_podがファンキーなものを追加するため、これはオフセットを間違って取得します(仮想関数テーブルのようなものだと思いますか?)。