lexical_castの話

id:DigitalGhost:20091228
ポリシーもそうだけど、そもそも型自体書きたくないよとか言ってみる。
というわけで
int n1 = lexical_cast("123");
boost::optional n1 = lexical_cast("456");
と書けるようにしてみました。
問題点を解決するのではなくてよりヒドイ方向にシフトしてみました

#include <typeinfo>
#include <sstream>
#include <string>
#include <boost/optional.hpp>
#include <boost/lexical_cast.hpp>
namespace detail {
    template<typename Source>
    struct lcast_auto_error_handling {
        Source const & src;
        lcast_auto_error_handling(Source const & src) : src(src) {}
        template<typename Target>
        operator boost::optional<Target>() const {
            return cast<Target>();
        }
        template<typename Target>
        operator Target() const {
            return throw_if_none(cast<Target>());
        }
    private:
        template<typename Target>
        boost::optional<Target> cast() const {
            std::stringstream ss;
            if ((ss << src).fail()) {
                return boost::optional<Target>();
            }
            Target res;
            if (!(ss >> res) || ss.get() != std::stringstream::traits_type::eof()) {
                return boost::optional<Target>();
            }
            return boost::optional<Target>(res);
        }
        template<typename Target>
        static Target throw_if_none(boost::optional<Target> const & value) {
            if (!value) {
                throw boost::bad_lexical_cast(typeid(Source), typeid(Target));
            }
            return value.get();
        }
    };
}

template<typename Source>
detail::lcast_auto_error_handling<Source> lexical_cast(Source const & src) {
    return detail::lcast_auto_error_handling<Source>(src);
}
#include<iostream>
int main() // テストコードは http://d.hatena.ne.jp/faith_and_brave/20091225/1261734967 から拝借
{
    try {
        int n1 = lexical_cast("123");
        std::cout << n1 << std::endl;

        int n2 = lexical_cast("xyz");
        static_cast<void>(n2); // no use
    }
    catch (boost::bad_lexical_cast&) {
        std::cout << "bad_lexical_cast" << std::endl;
    }

    boost::optional<int> n1 = lexical_cast("456");
    std::cout << n1.get() << std::endl;

    if (boost::optional<int> n2 = lexical_cast("xyz")) {
        std::cout << n2.get() << std::endl;
    }
    else {
        std::cout << "lexical_cast error" << std::endl;
    }
}