« なんとなくリフレクション in C++ | メイン | Pathtraq の API を公開しました »
2008年06月27日
C++ で自動型変換
C++ の拡張ライブラリである boost には、lexical_cast というライブラリがあって、iostream への入出力ができる型ならなんでも文字列化 (その逆も) できるので、とても便利です。でも、lexical_cast は、int → long のような変換の場合にも iostream を使った変換をしてしまうので、汎用のリフレクションコードを書こうとすると、そのままでは使いにくいです (オーバーヘッドが大きすぎる)。というわけで、変換前後の型に応じて、static_cast と lexical_cast を自動的に切り替えるようなキャスト関数を作ってみました。こんな感じで使います。
// calls lexical_cast<int>(123)
int i = intelligent_cast<int>("123");
// calls static_cast<long>(123)
long l = intelligent_cast<int>(123);
// calls std::string(const char*)
std::string s = intelligent_cast<std::string>("abc");
これで、不用意に数値型間や std::string → std::string のような変換 (コピー) が必要になる場合でも、速度の低下を心配する必要がなくなりました。
ライブラリのコードは以下のような感じ。boost におんぶにだっこなので簡単です (std::string については、実用上の観点から専用コードを追加しています) 。最新版は CodeRepos (/lang/cplusplus/reflection) においてあるので、バグ等ありましたら、指摘もしくは修正いただければ幸いです。
namespace intelligent_cast_ns {
template <typename Target, typename Source, bool IsConvertible>
struct cast_op {
Target operator()(const Source &s) const {
return boost::lexical_cast<Target>(s);
}
};
template <typename Target, typename Source>
struct cast_op<Target, Source, true> {
Target operator()(const Source &s) const {
return static_cast<Target>(s);
}
};
template <typename T>
struct cast_op<std::basic_string<T>, const T*, false> {
std::basic_string<T> operator()(const T* const &s) {
return s;
}
};
template <typename T, size_t N>
struct cast_op<std::basic_string<T>, T [N], false> {
std::basic_string<T> operator()(const T (&s)[N]) {
return s;
}
};
};
template <typename Target, typename Source>
Target intelligent_cast(const Source &s)
{
return intelligent_cast_ns::cast_op<Target, Source, boost::is_convertible<Target, Source>::value>()(s);
}
投稿者 kazuho : 2008年06月27日 17:22
トラックバック
このエントリーのトラックバックURL:
https://labs.cybozu.co.jp/cgi-bin/mt-admin/mt-tbp.cgi/1947