1 #ifndef BOOST_LEXICAL_CAST_INCLUDED
2 #define BOOST_LEXICAL_CAST_INCLUDED
4 // Boost lexical_cast.hpp header -------------------------------------------//
6 // See http://www.boost.org/libs/conversion for documentation.
7 // See end of this header for rights and permissions.
9 // what: lexical_cast custom keyword cast
10 // who: contributed by Kevlin Henney,
11 // enhanced with contributions from Terje Slettebo,
12 // with additional fixes and suggestions from Gennaro Prota,
13 // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov,
14 // Alexander Nasonov and other Boosters
15 // when: November 2000, March 2003, June 2005, June 2006
23 #include <boost/config.hpp>
24 #include <boost/limits.hpp>
25 #include <boost/mpl/if.hpp>
26 #include <boost/throw_exception.hpp>
27 #include <boost/type_traits/is_pointer.hpp>
28 #include <boost/call_traits.hpp>
29 #include <boost/static_assert.hpp>
30 #include <boost/detail/lcast_precision.hpp>
32 #ifdef BOOST_NO_STRINGSTREAM
38 #if defined(BOOST_NO_STRINGSTREAM) || \
39 defined(BOOST_NO_STD_WSTRING) || \
40 defined(BOOST_NO_STD_LOCALE)
41 #define DISABLE_WIDE_CHAR_SUPPORT
46 // exception used to indicate runtime lexical_cast failure
47 class bad_lexical_cast : public std::bad_cast
51 source(&typeid(void)), target(&typeid(void))
55 const std::type_info &source_type_arg,
56 const std::type_info &target_type_arg) :
57 source(&source_type_arg), target(&target_type_arg)
60 const std::type_info &source_type() const
64 const std::type_info &target_type() const
68 virtual const char *what() const throw()
70 return "bad lexical cast: "
71 "source type value could not be interpreted as target";
73 virtual ~bad_lexical_cast() throw()
77 const std::type_info *source;
78 const std::type_info *target;
81 namespace detail // selectors for choosing stream character type
83 template<typename Type>
89 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
90 template<class CharT, class Traits, class Alloc>
91 struct stream_char< std::basic_string<CharT,Traits,Alloc> >
97 #ifndef DISABLE_WIDE_CHAR_SUPPORT
98 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
100 struct stream_char<wchar_t>
102 typedef wchar_t type;
107 struct stream_char<wchar_t *>
109 typedef wchar_t type;
113 struct stream_char<const wchar_t *>
115 typedef wchar_t type;
118 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
120 struct stream_char<std::wstring>
122 typedef wchar_t type;
127 template<typename TargetChar, typename SourceChar>
130 typedef TargetChar type;
134 struct widest_char<char, wchar_t>
136 typedef wchar_t type;
140 namespace detail // deduce_char_traits template
142 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
143 template<class CharT, class Target, class Source>
144 struct deduce_char_traits
146 typedef std::char_traits<CharT> type;
149 template<class CharT, class Traits, class Alloc, class Source>
150 struct deduce_char_traits< CharT
151 , std::basic_string<CharT,Traits,Alloc>
158 template<class CharT, class Target, class Traits, class Alloc>
159 struct deduce_char_traits< CharT
161 , std::basic_string<CharT,Traits,Alloc>
167 template<class CharT, class Traits, class Alloc1, class Alloc2>
168 struct deduce_char_traits< CharT
169 , std::basic_string<CharT,Traits,Alloc1>
170 , std::basic_string<CharT,Traits,Alloc2>
178 namespace detail // lcast_src_length
180 // Return max. length of string representation of Source;
181 // 0 if unlimited (with exceptions for some types, see below).
182 // Values with limited string representation are placed to
183 // the buffer locally defined in lexical_cast function.
184 // 1 is returned for few types such as CharT const* or
185 // std::basic_string<CharT> that already have an internal
186 // buffer ready to be reused by lexical_stream_limited_src.
187 // Each specialization should have a correspondent operator<<
188 // defined in lexical_stream_limited_src.
189 template< class CharT // A result of widest_char transformation.
190 , class Source // Source type of lexical_cast.
192 struct lcast_src_length
194 BOOST_STATIC_CONSTANT(std::size_t, value = 0);
195 // To check coverage, build the test with
196 // bjam --v2 profile optimization=off
197 static void check_coverage() {}
201 struct lcast_src_length<char, bool>
203 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
204 static void check_coverage() {}
208 struct lcast_src_length<char, char>
210 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
211 static void check_coverage() {}
214 // No specializations for:
215 // lcast_src_length<char, signed char>
216 // lcast_src_length<char, unsigned char>
217 // lcast_src_length<char, signed char*>
218 // lcast_src_length<char, unsigned char*>
219 // lcast_src_length<char, signed char const*>
220 // lcast_src_length<char, unsigned char const*>
222 #ifndef DISABLE_WIDE_CHAR_SUPPORT
224 struct lcast_src_length<wchar_t, bool>
226 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
227 static void check_coverage() {}
231 struct lcast_src_length<wchar_t, char>
233 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
234 static void check_coverage() {}
237 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
239 struct lcast_src_length<wchar_t, wchar_t>
241 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
242 static void check_coverage() {}
248 struct lcast_src_length<char, char const*>
250 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
251 static void check_coverage() {}
255 struct lcast_src_length<char, char*>
257 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
258 static void check_coverage() {}
261 #ifndef DISABLE_WIDE_CHAR_SUPPORT
263 struct lcast_src_length<wchar_t, wchar_t const*>
265 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
266 static void check_coverage() {}
270 struct lcast_src_length<wchar_t, wchar_t*>
272 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
273 static void check_coverage() {}
277 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
278 template<class CharT, class Traits, class Alloc>
279 struct lcast_src_length< CharT, std::basic_string<CharT,Traits,Alloc> >
281 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
282 static void check_coverage() {}
286 struct lcast_src_length< char, std::basic_string<char> >
288 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
289 static void check_coverage() {}
292 #ifndef DISABLE_WIDE_CHAR_SUPPORT
294 struct lcast_src_length< wchar_t, std::basic_string<wchar_t> >
296 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
297 static void check_coverage() {}
302 // Helper for integral types.
303 // Notes on length calculation:
304 // Max length for 32bit int with grouping "\1" and thousands_sep ',':
305 // "-2,1,4,7,4,8,3,6,4,7"
307 // ^ - 1 digit not counted by digits10
308 // ^^^^^^^^^^^^^^^^^^ - digits10 * 2
310 // Constant is_specialized is used instead of constant 1
311 // to prevent buffer overflow in a rare case when
312 // <boost/limits.hpp> doesn't add missing specialization for
313 // numeric_limits<T> for some integral type T.
314 // When is_specialized is false, the whole expression is 0.
315 template<class Source>
316 struct lcast_src_length_integral
318 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
319 BOOST_STATIC_CONSTANT(std::size_t, value =
320 std::numeric_limits<Source>::is_signed +
321 std::numeric_limits<Source>::is_specialized + // == 1
322 std::numeric_limits<Source>::digits10 * 2
325 BOOST_STATIC_CONSTANT(std::size_t, value = 156);
326 BOOST_STATIC_ASSERT(sizeof(Source) * CHAR_BIT <= 256);
330 #define BOOST_AUX_LEXICAL_CAST_DEF1(CharT, T) template<> \
331 struct lcast_src_length<CharT, T> : lcast_src_length_integral<T> \
332 { static void check_coverage() {} };
334 #ifdef DISABLE_WIDE_CHAR_SUPPORT
335 #define BOOST_AUX_LEXICAL_CAST_DEF(T) BOOST_AUX_LEXICAL_CAST_DEF1(char, T)
337 #define BOOST_AUX_LEXICAL_CAST_DEF(T) \
338 BOOST_AUX_LEXICAL_CAST_DEF1(char, T) \
339 BOOST_AUX_LEXICAL_CAST_DEF1(wchar_t, T)
342 BOOST_AUX_LEXICAL_CAST_DEF(short)
343 BOOST_AUX_LEXICAL_CAST_DEF(unsigned short)
344 BOOST_AUX_LEXICAL_CAST_DEF(int)
345 BOOST_AUX_LEXICAL_CAST_DEF(unsigned int)
346 BOOST_AUX_LEXICAL_CAST_DEF(long)
347 BOOST_AUX_LEXICAL_CAST_DEF(unsigned long)
348 #if defined(BOOST_HAS_LONG_LONG)
349 BOOST_AUX_LEXICAL_CAST_DEF(boost::ulong_long_type)
350 BOOST_AUX_LEXICAL_CAST_DEF(boost::long_long_type )
351 #elif defined(BOOST_HAS_MS_INT64)
352 BOOST_AUX_LEXICAL_CAST_DEF(unsigned __int64)
353 BOOST_AUX_LEXICAL_CAST_DEF( __int64)
356 #undef BOOST_AUX_LEXICAL_CAST_DEF
357 #undef BOOST_AUX_LEXICAL_CAST_DEF1
359 #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
360 // Helper for floating point types.
361 // -1.23456789e-123456
365 // ^^^^^^^^ lcast_precision<Source>::value
368 // ^^^^^^ exponent (assumed 6 or less digits)
369 // sign + leading digit + decimal point + "e" + exponent sign == 5
370 template<class Source>
371 struct lcast_src_length_floating
374 std::numeric_limits<Source>::max_exponent10 <= 999999L &&
375 std::numeric_limits<Source>::min_exponent10 >= -999999L
377 BOOST_STATIC_CONSTANT(std::size_t, value =
378 5 + lcast_precision<Source>::value + 6
383 struct lcast_src_length<char,float>
384 : lcast_src_length_floating<float>
386 static void check_coverage() {}
390 struct lcast_src_length<char,double>
391 : lcast_src_length_floating<double>
393 static void check_coverage() {}
397 struct lcast_src_length<char,long double>
398 : lcast_src_length_floating<long double>
400 static void check_coverage() {}
403 #ifndef DISABLE_WIDE_CHAR_SUPPORT
405 struct lcast_src_length<wchar_t,float>
406 : lcast_src_length_floating<float>
408 static void check_coverage() {}
412 struct lcast_src_length<wchar_t,double>
413 : lcast_src_length_floating<double>
415 static void check_coverage() {}
419 struct lcast_src_length<wchar_t,long double>
420 : lcast_src_length_floating<long double>
422 static void check_coverage() {}
425 #endif // #ifndef DISABLE_WIDE_CHAR_SUPPORT
426 #endif // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
429 namespace detail // '0' and '-' constants
431 template<typename CharT> struct lcast_char_constants;
434 struct lcast_char_constants<char>
436 BOOST_STATIC_CONSTANT(char, zero = '0');
437 BOOST_STATIC_CONSTANT(char, minus = '-');
440 #ifndef DISABLE_WIDE_CHAR_SUPPORT
442 struct lcast_char_constants<wchar_t>
444 BOOST_STATIC_CONSTANT(wchar_t, zero = L'0');
445 BOOST_STATIC_CONSTANT(wchar_t, minus = L'-');
450 namespace detail // lexical_streambuf_fake
452 struct lexical_streambuf_fake
457 namespace detail // lcast_to_unsigned
459 #if (defined _MSC_VER)
460 # pragma warning( push )
461 // C4146: unary minus operator applied to unsigned type, result still unsigned
462 # pragma warning( disable : 4146 )
465 inline unsigned int lcast_to_unsigned(int value)
467 unsigned int uval = value;
468 return value < 0 ? -uval : uval;
471 inline unsigned long lcast_to_unsigned(long value)
473 unsigned long uval = value;
474 return value < 0 ? -uval : uval;
477 #if defined(BOOST_HAS_LONG_LONG)
478 inline boost::ulong_long_type lcast_to_unsigned(boost::long_long_type v)
480 boost::ulong_long_type uval = v;
481 return v < 0 ? -uval : uval;
483 #elif defined(BOOST_HAS_MS_INT64)
484 inline unsigned __int64 lcast_to_unsigned(__int64 value)
486 unsigned __int64 uval = value;
487 return value < 0 ? -uval : uval;
491 #if (defined _MSC_VER)
492 # pragma warning( pop ) // C4146: unary minus operator applied to unsigned type,
493 // result still unsigned
497 namespace detail // lcast_put_unsigned
499 template<class Traits, class T, class CharT>
500 CharT* lcast_put_unsigned(T n, CharT* finish)
502 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
503 BOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_signed);
505 CharT thousands_sep = 0;
507 #ifdef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
508 char const* grouping = "";
509 std::size_t const grouping_size = 0;
512 typedef std::numpunct<CharT> numpunct;
513 numpunct const& np = BOOST_USE_FACET(numpunct, loc);
514 std::string const& grouping = np.grouping();
515 std::string::size_type const grouping_size = grouping.size();
518 thousands_sep = np.thousands_sep();
521 std::string::size_type group = 0; // current group number
522 char last_grp_size = grouping[0] <= 0 ? CHAR_MAX : grouping[0];
523 // a) Since grouping is const, grouping[grouping.size()] returns 0.
524 // b) It's safe to assume here and below that CHAR_MAX
525 // is equivalent to unlimited grouping:
526 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
527 BOOST_STATIC_ASSERT(std::numeric_limits<T>::digits10 < CHAR_MAX);
529 typedef typename Traits::int_type int_type;
530 CharT const czero = lcast_char_constants<CharT>::zero;
531 int_type const zero = Traits::to_int_type(czero);
533 char left = last_grp_size;
540 if(group < grouping_size)
542 char const grp_size = grouping[group];
543 last_grp_size = grp_size <= 0 ? CHAR_MAX : grp_size;
546 left = last_grp_size;
548 Traits::assign(*finish, thousands_sep);
553 int_type const digit = static_cast<int_type>(n % 10U);
554 Traits::assign(*finish, Traits::to_char_type(zero + digit));
562 namespace detail // stream wrapper for handling lexical conversions
564 template<typename Target, typename Source, typename Traits>
568 typedef typename widest_char<
569 typename stream_char<Target>::type,
570 typename stream_char<Source>::type>::type char_type;
572 typedef Traits traits_type;
575 lexical_stream(char_type* = 0, char_type* = 0)
577 stream.unsetf(std::ios::skipws);
578 lcast_set_precision(stream, (Source*)0, (Target*)0);
582 #if defined(BOOST_NO_STRINGSTREAM)
583 stream.freeze(false);
586 bool operator<<(const Source &input)
588 return !(stream << input).fail();
590 template<typename InputStreamable>
591 bool operator>>(InputStreamable &output)
593 return !is_pointer<InputStreamable>::value &&
596 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
597 // GCC 2.9x lacks std::char_traits<>::eof().
598 // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
599 // configurations, which do provide std::char_traits<>::eof().
607 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
609 bool operator>>(std::string &output)
611 #if defined(BOOST_NO_STRINGSTREAM)
614 stream.str().swap(output);
617 #ifndef DISABLE_WIDE_CHAR_SUPPORT
618 bool operator>>(std::wstring &output)
620 stream.str().swap(output);
626 bool operator>>(std::basic_string<char_type,traits_type>& output)
628 stream.str().swap(output);
632 template<class Alloc>
633 bool operator>>(std::basic_string<char_type,traits_type,Alloc>& out)
635 std::basic_string<char_type,traits_type> str(stream.str());
636 out.assign(str.begin(), str.end());
641 #if defined(BOOST_NO_STRINGSTREAM)
642 std::strstream stream;
643 #elif defined(BOOST_NO_STD_LOCALE)
644 std::stringstream stream;
646 std::basic_stringstream<char_type,traits_type> stream;
651 namespace detail // optimized stream wrapper
653 // String representation of Source has an upper limit.
654 template< class CharT // a result of widest_char transformation
655 , class Base // lexical_streambuf_fake or basic_streambuf<CharT>
656 , class Traits // usually char_traits<CharT>
658 class lexical_stream_limited_src : public Base
660 // A string representation of Source is written to [start, finish).
661 // Currently, it is assumed that [start, finish) is big enough
662 // to hold a string representation of any Source value.
668 static void widen_and_assign(char*p, char ch)
670 Traits::assign(*p, ch);
673 #ifndef DISABLE_WIDE_CHAR_SUPPORT
674 static void widen_and_assign(wchar_t* p, char ch)
677 wchar_t w = BOOST_USE_FACET(std::ctype<wchar_t>, loc).widen(ch);
678 Traits::assign(*p, w);
681 static void widen_and_assign(wchar_t* p, wchar_t ch)
683 Traits::assign(*p, ch);
686 static void widen_and_assign(char*, wchar_t ch); // undefined
689 template<class OutputStreamable>
690 bool lcast_put(const OutputStreamable& input)
692 this->setp(start, finish);
693 std::basic_ostream<CharT> stream(static_cast<Base*>(this));
694 lcast_set_precision(stream, (OutputStreamable*)0);
695 bool const result = !(stream << input).fail();
696 finish = this->pptr();
701 lexical_stream_limited_src(lexical_stream_limited_src const&);
702 void operator=(lexical_stream_limited_src const&);
706 lexical_stream_limited_src(CharT* start, CharT* finish)
713 template<class Alloc>
714 bool operator<<(std::basic_string<CharT,Traits,Alloc> const& str)
716 start = const_cast<CharT*>(str.data());
717 finish = start + str.length();
721 bool operator<<(bool);
722 bool operator<<(char);
723 #if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
724 bool operator<<(wchar_t);
726 bool operator<<(CharT const*);
727 bool operator<<(short);
728 bool operator<<(int);
729 bool operator<<(long);
730 bool operator<<(unsigned short);
731 bool operator<<(unsigned int);
732 bool operator<<(unsigned long);
733 #if defined(BOOST_HAS_LONG_LONG)
734 bool operator<<(boost::ulong_long_type);
735 bool operator<<(boost::long_long_type );
736 #elif defined(BOOST_HAS_MS_INT64)
737 bool operator<<(unsigned __int64);
738 bool operator<<( __int64);
740 // These three operators use ostream and streambuf.
741 // lcast_streambuf_for_source<T>::value is true.
742 bool operator<<(float);
743 bool operator<<(double);
744 bool operator<<(long double);
748 // Generic istream-based algorithm.
749 // lcast_streambuf_for_target<InputStreamable>::value is true.
750 template<typename InputStreamable>
751 bool operator>>(InputStreamable& output)
753 #if (defined _MSC_VER)
754 # pragma warning( push )
755 // conditional expression is constant
756 # pragma warning( disable : 4127 )
758 if(is_pointer<InputStreamable>::value)
761 this->setg(start, start, finish);
762 std::basic_istream<CharT> stream(static_cast<Base*>(this));
763 stream.unsetf(std::ios::skipws);
764 lcast_set_precision(stream, (InputStreamable*)0);
765 #if (defined _MSC_VER)
766 # pragma warning( pop )
768 return stream >> output &&
770 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
771 // GCC 2.9x lacks std::char_traits<>::eof().
772 // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
773 // configurations, which do provide std::char_traits<>::eof().
781 bool operator>>(CharT&);
783 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
784 // This #if is in sync with lcast_streambuf_for_target
786 bool operator>>(std::string&);
788 #ifndef DISABLE_WIDE_CHAR_SUPPORT
789 bool operator>>(std::wstring&);
793 template<class Alloc>
794 bool operator>>(std::basic_string<CharT,Traits,Alloc>& str)
796 str.assign(start, finish);
802 template<typename CharT, class Base, class Traits>
803 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
806 typedef typename Traits::int_type int_type;
807 CharT const czero = lcast_char_constants<CharT>::zero;
808 int_type const zero = Traits::to_int_type(czero);
809 Traits::assign(*start, Traits::to_char_type(zero + value));
814 template<typename CharT, class Base, class Traits>
815 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
818 widen_and_assign(start, ch);
823 #if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
824 template<typename CharT, class Base, class Traits>
825 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
828 widen_and_assign(start, ch);
834 template<typename CharT, class Base, class Traits>
835 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
838 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
842 CharT const minus = lcast_char_constants<CharT>::minus;
843 Traits::assign(*start, minus);
848 template<typename CharT, class Base, class Traits>
849 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
852 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
856 CharT const minus = lcast_char_constants<CharT>::minus;
857 Traits::assign(*start, minus);
862 template<typename CharT, class Base, class Traits>
863 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
866 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
870 CharT const minus = lcast_char_constants<CharT>::minus;
871 Traits::assign(*start, minus);
876 #if defined(BOOST_HAS_LONG_LONG)
877 template<typename CharT, class Base, class Traits>
878 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
879 boost::long_long_type n)
881 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
885 CharT const minus = lcast_char_constants<CharT>::minus;
886 Traits::assign(*start, minus);
890 #elif defined(BOOST_HAS_MS_INT64)
891 template<typename CharT, class Base, class Traits>
892 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
895 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
899 CharT const minus = lcast_char_constants<CharT>::minus;
900 Traits::assign(*start, minus);
906 template<typename CharT, class Base, class Traits>
907 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
910 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
914 template<typename CharT, class Base, class Traits>
915 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
918 start = lcast_put_unsigned<Traits>(n, finish);
922 template<typename CharT, class Base, class Traits>
923 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
926 start = lcast_put_unsigned<Traits>(n, finish);
930 #if defined(BOOST_HAS_LONG_LONG)
931 template<typename CharT, class Base, class Traits>
932 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
933 boost::ulong_long_type n)
935 start = lcast_put_unsigned<Traits>(n, finish);
938 #elif defined(BOOST_HAS_MS_INT64)
939 template<typename CharT, class Base, class Traits>
940 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
943 start = lcast_put_unsigned<Traits>(n, finish);
948 template<typename CharT, class Base, class Traits>
949 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
952 return this->lcast_put(val);
955 template<typename CharT, class Base, class Traits>
956 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
959 return this->lcast_put(val);
962 template<typename CharT, class Base, class Traits>
963 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
966 return this->lcast_put(val);
969 template<typename CharT, class Base, class Traits>
970 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
973 start = const_cast<CharT*>(str);
974 finish = start + Traits::length(str);
978 template<typename CharT, class Base, class Traits>
979 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
982 bool const ok = (finish - start == 1);
984 Traits::assign(output, *start);
988 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
989 template<typename CharT, class Base, class Traits>
990 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
993 str.assign(start, finish);
997 #ifndef DISABLE_WIDE_CHAR_SUPPORT
998 template<typename CharT, class Base, class Traits>
999 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
1002 str.assign(start, finish);
1009 namespace detail // lcast_streambuf_for_source
1011 // Returns true if optimized stream wrapper needs ostream for writing.
1012 template<class Source>
1013 struct lcast_streambuf_for_source
1015 BOOST_STATIC_CONSTANT(bool, value = false);
1019 struct lcast_streambuf_for_source<float>
1021 BOOST_STATIC_CONSTANT(bool, value = true);
1025 struct lcast_streambuf_for_source<double>
1027 BOOST_STATIC_CONSTANT(bool, value = true);
1031 struct lcast_streambuf_for_source<long double>
1033 BOOST_STATIC_CONSTANT(bool, value = true);
1037 namespace detail // lcast_streambuf_for_target
1039 // Returns true if optimized stream wrapper needs istream for reading.
1040 template<class Target>
1041 struct lcast_streambuf_for_target
1043 BOOST_STATIC_CONSTANT(bool, value = true);
1047 struct lcast_streambuf_for_target<char>
1049 BOOST_STATIC_CONSTANT(bool, value = false);
1052 #if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
1054 struct lcast_streambuf_for_target<wchar_t>
1056 BOOST_STATIC_CONSTANT(bool, value = false);
1060 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1061 template<class Traits, class Alloc>
1062 struct lcast_streambuf_for_target<
1063 std::basic_string<char,Traits,Alloc> >
1065 BOOST_STATIC_CONSTANT(bool, value = false);
1068 #ifndef DISABLE_WIDE_CHAR_SUPPORT
1069 template<class Traits, class Alloc>
1070 struct lcast_streambuf_for_target<
1071 std::basic_string<wchar_t,Traits,Alloc> >
1073 BOOST_STATIC_CONSTANT(bool, value = false);
1078 struct lcast_streambuf_for_target<std::string>
1080 BOOST_STATIC_CONSTANT(bool, value = false);
1083 #ifndef DISABLE_WIDE_CHAR_SUPPORT
1085 struct lcast_streambuf_for_target<std::wstring>
1087 BOOST_STATIC_CONSTANT(bool, value = false);
1093 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1095 // call-by-const reference version
1100 struct array_to_pointer_decay
1105 template<class T, std::size_t N>
1106 struct array_to_pointer_decay<T[N]>
1108 typedef const T * type;
1111 template< typename Target
1113 , bool Unlimited // string representation of Source is unlimited
1116 Target lexical_cast(
1117 BOOST_DEDUCED_TYPENAME boost::call_traits<Source>::param_type arg,
1118 CharT* buf, std::size_t src_len)
1120 typedef BOOST_DEDUCED_TYPENAME
1121 deduce_char_traits<CharT,Target,Source>::type traits;
1123 typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
1124 lcast_streambuf_for_target<Target>::value ||
1125 lcast_streambuf_for_source<Source>::value
1126 , std::basic_streambuf<CharT>
1127 , lexical_streambuf_fake
1130 BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
1132 , detail::lexical_stream<Target,Source,traits>
1133 , detail::lexical_stream_limited_src<CharT,base,traits>
1134 >::type interpreter(buf, buf + src_len);
1136 // The original form, reproduced below, is more elegant
1137 // but yields a spurious C4701 warning ("possible use of
1138 // "result" before initialization") with VC7.1 (/W4).
1142 // if(!(interpreter << arg && interpreter >> result))
1143 // throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)));
1146 if(interpreter << arg) {
1148 if (interpreter >> result)
1151 throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)));
1152 return Target(); // normally never reached (throw_exception)
1156 template<typename Target, typename Source>
1157 inline Target lexical_cast(const Source &arg)
1159 typedef typename detail::array_to_pointer_decay<Source>::type src;
1161 typedef typename detail::widest_char<
1162 typename detail::stream_char<Target>::type
1163 , typename detail::stream_char<src>::type
1166 typedef detail::lcast_src_length<char_type, src> lcast_src_length;
1167 std::size_t const src_len = lcast_src_length::value;
1168 char_type buf[src_len + 1];
1169 lcast_src_length::check_coverage();
1170 return detail::lexical_cast<Target, src, !src_len>(arg, buf, src_len);
1175 // call-by-value fallback version (deprecated)
1177 template<typename Target, typename Source>
1178 Target lexical_cast(Source arg)
1180 typedef typename detail::widest_char<
1181 BOOST_DEDUCED_TYPENAME detail::stream_char<Target>::type
1182 , BOOST_DEDUCED_TYPENAME detail::stream_char<Source>::type
1185 typedef std::char_traits<char_type> traits;
1186 detail::lexical_stream<Target, Source, traits> interpreter;
1189 if(!(interpreter << arg && interpreter >> result))
1190 throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)));
1197 // Copyright Kevlin Henney, 2000-2005.
1198 // Copyright Alexander Nasonov, 2006-2007.
1200 // Distributed under the Boost Software License, Version 1.0. (See
1201 // accompanying file LICENSE_1_0.txt or copy at
1202 // http://www.boost.org/LICENSE_1_0.txt)
1204 #undef DISABLE_WIDE_CHAR_SUPPORT