続 構造体のバイナリ読み書き

構造体を入れ子にした場合に対応しました。
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()関数の生成にも使えます。