随笔-167  评论-8  文章-0  trackbacks-0

Source

#include <cstddef>

#include <string>

#include <typeinfo>

//#include <boost/config.hpp>

#include <boost/limits.hpp>

#include <boost/throw_exception.hpp>

#include <boost/type_traits/is_pointer.hpp>

#include <sstream>

 

 

 

//

namespace kimi_boost

{

    // exception used to indicate runtime lexical_cast failure

    class bad_lexical_cast : public std::bad_cast

    {

    public:

        bad_lexical_cast() :

        source(&typeid(void)), target(&typeid(void))

        {

        }

        bad_lexical_cast(

           const std::type_info &source_type,

            const std::type_info &target_type) :

            source(&source_type), target(&target_type)

        {

        }

        const std::type_info &source_type() const

        {

            return *source;

        }

        const std::type_info &target_type() const

        {

            return *target;

        }

        virtual const char *what() const throw()

        {

            return "bad lexical cast: "

                   "source type value could not be interpreted as target";

        }

        virtual ~bad_lexical_cast() throw()

        {

        }

    private:

        const std::type_info *source;

        const std::type_info *target;

    };

 

 

   

    namespace detail // stream wrapper for handling lexical conversions

    {

        template<typename Target, typename Source>

        class lexical_stream

        {

        private:

            typedef char char_type;

                     std::basic_stringstream<char_type> stream;

 

        public:

            lexical_stream()

            {

                stream.unsetf(std::ios::skipws);

                if(std::numeric_limits<Target>::is_specialized)

                    stream.precision(std::numeric_limits<Target>::digits10 + 1);

                else if(std::numeric_limits<Source>::is_specialized)

                    stream.precision(std::numeric_limits<Source>::digits10 + 1);

            }

 

            ~lexical_stream()

            {

            }

 

                     //Source类型输入到流中

            bool operator<<(const Source &input)

            {

                return !(stream << input).fail();

            }

 

                     //把流转换为Target类型输出

            template<typename InputStreamable>

            bool operator>>(InputStreamable &output)

            {

                            return !boost::is_pointer<InputStreamable>::value &&

                       stream >> output &&

                       stream.get() ==

                           std::char_traits<char_type>::eof();

            }

 

                     //string特化

                     template<>

            bool operator>>(std::string &output)

            {

                output = stream.str();

                return true;

            }

        };//class lexical_stream

    }//namespace detail

 

 

    namespace detail

    {

        template<class T>

        struct array_to_pointer_decay

        {

            typedef T type;

        };

 

        template<class T, std::size_t N>

        struct array_to_pointer_decay<T[N]>

        {

            typedef const T * type;

        };

    }

 

    template<typename Target, typename Source>

    Target lexical_cast(const Source &arg)

    {

        typedef typename detail::array_to_pointer_decay<Source>::type NewSource;

 

        detail::lexical_stream<Target, NewSource> interpreter;

        Target result;

 

        if(!(interpreter << arg && interpreter >> result))

                     boost::throw_exception(bad_lexical_cast(typeid(NewSource), typeid(Target)));

        return result;

    }

}

Test code

void kimi_lexical_cast_test()

{

       try

       {

              int i=kimi_boost::lexical_cast<int>("4365");

              float f=kimi_boost::lexical_cast<float>("234.546");

              double d=kimi_boost::lexical_cast<double>("24534.546345");

              std::string s=kimi_boost::lexical_cast<std::string>(24534.546345);

       }

       catch(kimi_boost::bad_lexical_cast& e)

       {

              cout<<e.what()<<endl;

       }

 

       try{

              int i2=kimi_boost::lexical_cast<int>("0.335");

       }

       catch(kimi_boost::bad_lexical_cast& e)

       {

              cout<<"source type: "<<e.source_type().name()<<endl;

              cout<<"target type: "<<e.target_type().name()<<endl;

              cout<<e.what()<<endl;

       }

}

Output

source type: char const *

target type: int

bad lexical cast: source type value could not be interpreted as target

posted on 2010-05-27 10:37 老马驿站 阅读(1208) 评论(0)  编辑 收藏 引用 所属分类: Boost