« なんとなくリフレクション 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:
http://labs.cybozu.co.jp/cgi-bin/mt-admin/mt-tbp.cgi/1947