続 構造体のバイナリ読み書き
構造体を入れ子にした場合に対応しました。
binary_io.hppの差分
struct_traits.hppの差分
struct inner { boost::uint32_t a; char b; }; struct outer { inner a; char b; }; namespace hamigaki { template<> struct struct_traits<inner> { typedef boost::mpl::list< hamigaki::member<inner, boost::uint32_t, &inner::a>, hamigaki::member<inner, char, &inner::b> > members; }; template<> struct struct_traits<outer> { typedef boost::mpl::list< hamigaki::member<outer, inner, &outer::a>, hamigaki::member<outer, char, &outer::b> > members; }; } // namespace hamigaki int main() { std::cout << "sizeof(inner) = " << sizeof(inner) << std::endl; std::cout << "struct_size<inner> = " << hamigaki::struct_size<inner>::type::value << std::endl; std::cout << "sizeof(outer) = " << sizeof(outer) << std::endl; std::cout << "struct_size<outer> = " << hamigaki::struct_size<outer>::type::value << std::endl; }
結果は環境によって異なりますが、VC8/Win32だとこうなりました。
sizeof(inner) = 8
struct_size<inner> = 5
sizeof(outer) = 12
struct_size<outer> = 6
構造体innerのサイズはパディングなしで5バイトで、それを含む構造体outerでは1バイト足した6バイトになっています。(昨日のバージョンではsizeof(inner)+1で9バイトになっていました)
また、バイナリにパディングを追加できるようになりました。
上の例で、outer::bの後ろに2バイトのパディングを置く場合はこうします。
template<> struct struct_traits<outer> { typedef boost::mpl::list< hamigaki::member<outer, inner, &outer::a>, hamigaki::member<outer, char, &outer::b>, hamigaki::padding<2> > members; };
これでそこそこ使えるものになったのではないかと思います。
一旦struct_traitsを作っておけばメンバ変数を辿れるので、デバッグ出力とかBoost.Serializationのserialize()関数の生成にも使えます。