std::streampos

lzh_file.hppのヘッダI/Oを書き換えるつもりでしたが、面倒くさくなってやめました。
代わりにseek関連の処理をまとめました。
<hamigaki/iostreams/seek.hpp>
多くの32ビット環境ではstd::streamoffが32ビットですが、std::streamposはそれ以上の精度を持っていることがあります。
そのため、Boost.Iostreamsでは(処理系依存の方法で)可能な限りstd::streamposからオフセットを64ビットの精度で取り出す関数position_to_offset()が用意されています。
このオフセットを表現するのにstd::streamoffでは足りないので、代わりにboost::iostreams::stream_offsetを使います。
これらの名前がどうにも長く、コードが読みづらかったので短縮形を用意しました。

typedef boost::iostreams::stream_offset stream_offset;

inline stream_offset to_offset(std::streampos pos)
{
    return boost::iostreams::position_to_offset(pos);
}

また、現在位置を取得するためにseek(t, 0, cur)する常套句と、streamposの代わりにstream_offsetを返すバージョンを追加しました。

// tのストリーム位置を返す
template<typename T>
inline std::streampos tell(T& t)
{
    return boost::iostreams::seek(t, 0, std::ios_base::cur);
}

// tのストリーム位置を先頭からのオフセットで返す。
template<typename T>
inline stream_offset tell_offset(T& t)
{
    return iostreams::to_offset(iostreams::tell(t));
}

これらを組み込んだだけで、そこそこコードを削れました。
また、コードの意図もはっきりします。


使っていて気が付いたんですが、(少なくともVC8付属のものでは)std::streampos同士の引き算などで意図せずオフセットの精度が落ちることがありました。
なので、std::streamposに演算を施す場合は、一旦stream_offsetに変換しないといけません。
これに関してコンパイラは警告を出してくれない(std::streamposの中でキャストしている)ので、注意深くコーディングする必要があります。
どうせならstd::streamposも別クラスで置き換えてくれれば楽だったんですけどね。