続code_converter for float
今回はstate_typeを使う必要がなさそうなので、state_typeをmbstate_tに戻しました。
codecvt<float_type,char,mbstate_t>の派生クラスとして、codecvt_u8とcodecvt_s16_leを作ることにします。
namespace std
{
// デフォルト
template<>
class codecvt<hamigaki::audio::float_type,char,mbstate_t>
{
// 略
};
} // namespace std
namespace hamigaki { namespace audio {
// 符号なし8ビット
class codecvt_u8
: public std::codecvt<float_type,char,std::mbstate_t>
{
// 略
};
// 符号あり16ビット(リトルエンディアン)
class codecvt_s16_le
: public std::codecvt<float_type,char,std::mbstate_t>
{
// 略
};
} } // End namespaces audio, hamigaki.
// codecvt_holderの特殊化
namespace boost { namespace iostreams { namespace detail {
template<>
struct codecvt_holder<
std::codecvt<hamigaki::audio::float_type,char,std::mbstate_t>
>
{
typedef std::codecvt<
hamigaki::audio::float_type,char,std::mbstate_t> codecvt_type;
codecvt_holder()
{
if (!std::has_facet<codecvt_type>(loc_))
loc_ = std::locale(loc_, new codecvt_type);
reset_codecvt();
}
const codecvt_type& get() const
{
return *codecvt_;
}
void imbue(const std::locale& loc)
{
loc_ = loc;
reset_codecvt();
}
void reset_codecvt()
{
codecvt_ = &std::use_facet<codecvt_type>(loc_);
}
std::locale loc_;
const codecvt_type* codecvt_;
};
} } } // End namespaces detail, iostreams, boost.code_converterの実装に使われているcodecvt_holderはcodecvt<wchar_t,char,mbstate_t>でのみ特殊化されていて、デフォルト実装はファセットがコピー可能であることを要求します。また、imbue()の実装も空なので、コンパイル時にファセットが固定されてしまいます。
このままではファセットの意味がないので、独自に特殊化しています。codecvt<wchar_t,char,mbstate_t>と違い、codecvt<float_type,char,mbstate_t>は標準のファセットではないので、グローバルロケールに含まれない可能性があります。そのため、コンストラクタの処理が少し増えています。