はかせのラボ

私の頭の中を書いていく雑記ブログです

boost boost::lexical_cast読んでみる

あいさつ

どうも、はかせです。
今回は前回動作を確認したboost::lexical_castが
どのような実装になっているのかコードを読んでみたいと思います。

では読んでみる

VisualStudioを使っているなら関数にポインタを合わせてF12押せば
その関数の定義へジャンプできます。

とりあえずそれを繰り返して行き着くとこまで行ってみたいと思います。
まずは前回のこの辺りから飛んでみます。

testFloat = lexical_cast<float>(testString);

飛んだらここにきました。

template <typename Target, typename Source>
inline Target lexical_cast(const Source &arg)
{
    Target result = Target();

    if (!boost::conversion::detail::try_lexical_convert(arg, result)) {
        boost::conversion::detail::throw_bad_cast<Source, Target>();
    }

    return result;
}

んーと
try_lexical_convertなる関数に渡されたものと
変換したい型のインスタンスを渡してそのbool値でエラー判定する
といった感じですかね。

今回の私の例なら渡されたもの=testString
変換したい型=floatですね。

ではではお次はtry_lexical_convertの実装行ってみますかね。

template <typename Target, typename Source>
inline bool try_lexical_convert(const Source& arg, Target& result)
{
    typedef BOOST_DEDUCED_TYPENAME boost::detail::array_to_pointer_decay<Source>::type src;

    typedef boost::integral_constant<
        bool,
        boost::detail::is_xchar_to_xchar<Target, src >::value ||
        boost::detail::is_char_array_to_stdstring<Target, src >::value ||
        boost::detail::is_char_array_to_booststring<Target, src >::value ||
        (
             boost::is_same<Target, src >::value &&
             (boost::detail::is_stdstring<Target >::value || boost::detail::is_booststring<Target >::value)
        ) ||
        (
             boost::is_same<Target, src >::value &&
             boost::detail::is_character<Target >::value
        )
    > shall_we_copy_t;

    typedef boost::detail::is_arithmetic_and_not_xchars<Target, src >
    shall_we_copy_with_dynamic_check_t;

    // We do evaluate second `if_` lazily to avoid unnecessary instantiations
    // of `shall_we_copy_with_dynamic_check_t` and improve compilation times.
    typedef BOOST_DEDUCED_TYPENAME boost::conditional<
        shall_we_copy_t::value,
        boost::type_identity<boost::detail::copy_converter_impl<Target, src > >,
        boost::conditional<
             shall_we_copy_with_dynamic_check_t::value,
             boost::detail::dynamic_num_converter_impl<Target, src >,
             boost::detail::lexical_converter_impl<Target, src >
        >
    >::type caster_type_lazy;

    typedef BOOST_DEDUCED_TYPENAME caster_type_lazy::type caster_type;

    return caster_type::try_convert(arg, result);
}

・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
読む気が失せてくる右ストレート打ってくるのやめてくれませんかね?

あっでもコメントがある。
きっとこれを読めば何やってるかわかりやすく教えてくれてるはず。
どれどれ・・・・

多分
不必要なインスタンス化を避けるため2つ目のifを遅延評価します
そしてコンパイル時間を短縮します
的な感じかな・・・?(英語は苦手でもなければ得意でもないTHE・中途半端)

まぁ確かにそうしてる理由を
コメントに残すっていうのは正しいと思いますし、
そういうコメントのみがある方がいいという意見もわかります。

でもですよ?
このコードを後から読んで処理が全部理解できるんですかね・・・?
単純に私の能力不足?それなら仕方ありません。
頑張って読みますよ・・・(´;ω;`)

とりあえず大事そうなstructが2つありました。

template <class T, T val>
struct integral_constant
{
  typedef mpl::integral_c_tag tag;
  typedef T value_type;
  typedef integral_constant<T, val> type;
  static const T value = val;

  operator const mpl::integral_c<T, val>& ()const
  {
     static const char data[sizeof(long)] = { 0 };
     static const void* pdata = data;
     return *(reinterpret_cast<const mpl::integral_c<T, val>*>(pdata));
  }
  BOOST_CONSTEXPR operator T()const { return val; }
};

template <bool b, class T, class U> struct conditional { typedef T type; };
template <class T, class U> struct conditional<false, T, U> { typedef U type; };

どうやらこの2つのstructとbool値
それとtypedefの型名置き換えを使って
ケースバイケースのtry_convertメソッドを呼んでいるみたいです。

try_convertはストリームを使って変換をかけているようでした。
(今の私のC++力ではそれぐらいしかわかりませんでした)

あとがき

今回はboostの中身を読んでみました。
過去何度かライブラリやOSSソースコードを読んだことがあったので
文中で書いてるほどダメージは受けてなかったりします。

ただこんだけtypedefが連発されると
だんだん何が何かわかんなくなってきますね。
boostって全部こんな感じなんですかね。

ただtemplate + typedef(多分私はusing使うかな)
渡した型によってのケースバイケースの処理を
記述を変えずに実現できるっていうのはすごいなと思いました。

確かにboostのコード読むのは勉強になりますね。
・・・時間かかるけど…(-∀-)ボソッ…

今後も時間があれば今回みたく読んでみたいと思います。

それでは今回はこの辺でノシ