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/type_traits/make_unsigned.hpp>
29 #include <boost/call_traits.hpp>
30 #include <boost/static_assert.hpp>
31 #include <boost/detail/lcast_precision.hpp>
32 #include <boost/detail/workaround.hpp>
34 #ifndef BOOST_NO_STD_LOCALE
38 #ifdef BOOST_NO_STRINGSTREAM
44 #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
45 #define BOOST_LCAST_NO_WCHAR_T
48 #ifdef BOOST_NO_TYPEID
49 #define BOOST_LCAST_THROW_BAD_CAST(S, T) throw_exception(bad_lexical_cast())
51 #define BOOST_LCAST_THROW_BAD_CAST(Source, Target) \
52 throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)))
57 // exception used to indicate runtime lexical_cast failure
58 class bad_lexical_cast : public std::bad_cast
60 #if defined(__BORLANDC__) && BOOST_WORKAROUND( __BORLANDC__, < 0x560 )
61 // under bcc32 5.5.1 bad_cast doesn't derive from exception
62 , public std::exception
68 #ifndef BOOST_NO_TYPEID
69 source(&typeid(void)), target(&typeid(void))
71 source(0), target(0) // this breaks getters
77 const std::type_info &source_type_arg,
78 const std::type_info &target_type_arg) :
79 source(&source_type_arg), target(&target_type_arg)
83 const std::type_info &source_type() const
87 const std::type_info &target_type() const
92 virtual const char *what() const throw()
94 return "bad lexical cast: "
95 "source type value could not be interpreted as target";
97 virtual ~bad_lexical_cast() throw()
101 const std::type_info *source;
102 const std::type_info *target;
105 namespace detail // selectors for choosing stream character type
107 template<typename Type>
113 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
114 template<class CharT, class Traits, class Alloc>
115 struct stream_char< std::basic_string<CharT,Traits,Alloc> >
121 #ifndef BOOST_LCAST_NO_WCHAR_T
122 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
124 struct stream_char<wchar_t>
126 typedef wchar_t type;
131 struct stream_char<wchar_t *>
133 typedef wchar_t type;
137 struct stream_char<const wchar_t *>
139 typedef wchar_t type;
142 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
144 struct stream_char<std::wstring>
146 typedef wchar_t type;
151 template<typename TargetChar, typename SourceChar>
154 typedef TargetChar type;
158 struct widest_char<char, wchar_t>
160 typedef wchar_t type;
164 namespace detail // deduce_char_traits template
166 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
167 template<class CharT, class Target, class Source>
168 struct deduce_char_traits
170 typedef std::char_traits<CharT> type;
173 template<class CharT, class Traits, class Alloc, class Source>
174 struct deduce_char_traits< CharT
175 , std::basic_string<CharT,Traits,Alloc>
182 template<class CharT, class Target, class Traits, class Alloc>
183 struct deduce_char_traits< CharT
185 , std::basic_string<CharT,Traits,Alloc>
191 template<class CharT, class Traits, class Alloc1, class Alloc2>
192 struct deduce_char_traits< CharT
193 , std::basic_string<CharT,Traits,Alloc1>
194 , std::basic_string<CharT,Traits,Alloc2>
202 namespace detail // lcast_src_length
204 // Return max. length of string representation of Source;
205 // 0 if unlimited (with exceptions for some types, see below).
206 // Values with limited string representation are placed to
207 // the buffer locally defined in lexical_cast function.
208 // 1 is returned for few types such as CharT const* or
209 // std::basic_string<CharT> that already have an internal
210 // buffer ready to be reused by lexical_stream_limited_src.
211 // Each specialization should have a correspondent operator<<
212 // defined in lexical_stream_limited_src.
213 template< class CharT // A result of widest_char transformation.
214 , class Source // Source type of lexical_cast.
216 struct lcast_src_length
218 BOOST_STATIC_CONSTANT(std::size_t, value = 0);
219 // To check coverage, build the test with
220 // bjam --v2 profile optimization=off
221 static void check_coverage() {}
225 struct lcast_src_length<char, bool>
227 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
228 static void check_coverage() {}
232 struct lcast_src_length<char, char>
234 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
235 static void check_coverage() {}
238 // No specializations for:
239 // lcast_src_length<char, signed char>
240 // lcast_src_length<char, unsigned char>
241 // lcast_src_length<char, signed char*>
242 // lcast_src_length<char, unsigned char*>
243 // lcast_src_length<char, signed char const*>
244 // lcast_src_length<char, unsigned char const*>
246 #ifndef BOOST_LCAST_NO_WCHAR_T
248 struct lcast_src_length<wchar_t, bool>
250 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
251 static void check_coverage() {}
255 struct lcast_src_length<wchar_t, char>
257 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
258 static void check_coverage() {}
261 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
263 struct lcast_src_length<wchar_t, wchar_t>
265 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
266 static void check_coverage() {}
272 struct lcast_src_length<char, char const*>
274 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
275 static void check_coverage() {}
279 struct lcast_src_length<char, char*>
281 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
282 static void check_coverage() {}
285 #ifndef BOOST_LCAST_NO_WCHAR_T
287 struct lcast_src_length<wchar_t, wchar_t const*>
289 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
290 static void check_coverage() {}
294 struct lcast_src_length<wchar_t, wchar_t*>
296 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
297 static void check_coverage() {}
301 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
302 template<class CharT, class Traits, class Alloc>
303 struct lcast_src_length< CharT, std::basic_string<CharT,Traits,Alloc> >
305 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
306 static void check_coverage() {}
310 struct lcast_src_length< char, std::basic_string<char> >
312 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
313 static void check_coverage() {}
316 #ifndef BOOST_LCAST_NO_WCHAR_T
318 struct lcast_src_length< wchar_t, std::basic_string<wchar_t> >
320 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
321 static void check_coverage() {}
326 // Helper for integral types.
327 // Notes on length calculation:
328 // Max length for 32bit int with grouping "\1" and thousands_sep ',':
329 // "-2,1,4,7,4,8,3,6,4,7"
331 // ^ - 1 digit not counted by digits10
332 // ^^^^^^^^^^^^^^^^^^ - digits10 * 2
334 // Constant is_specialized is used instead of constant 1
335 // to prevent buffer overflow in a rare case when
336 // <boost/limits.hpp> doesn't add missing specialization for
337 // numeric_limits<T> for some integral type T.
338 // When is_specialized is false, the whole expression is 0.
339 template<class Source>
340 struct lcast_src_length_integral
342 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
343 BOOST_STATIC_CONSTANT(std::size_t, value =
344 std::numeric_limits<Source>::is_signed +
345 std::numeric_limits<Source>::is_specialized + // == 1
346 std::numeric_limits<Source>::digits10 * 2
349 BOOST_STATIC_CONSTANT(std::size_t, value = 156);
350 BOOST_STATIC_ASSERT(sizeof(Source) * CHAR_BIT <= 256);
354 #define BOOST_LCAST_DEF1(CharT, T) \
355 template<> struct lcast_src_length<CharT, T> \
356 : lcast_src_length_integral<T> \
357 { static void check_coverage() {} };
359 #ifdef BOOST_LCAST_NO_WCHAR_T
360 #define BOOST_LCAST_DEF(T) BOOST_LCAST_DEF1(char, T)
362 #define BOOST_LCAST_DEF(T) \
363 BOOST_LCAST_DEF1(char, T) \
364 BOOST_LCAST_DEF1(wchar_t, T)
367 BOOST_LCAST_DEF(short)
368 BOOST_LCAST_DEF(unsigned short)
370 BOOST_LCAST_DEF(unsigned int)
371 BOOST_LCAST_DEF(long)
372 BOOST_LCAST_DEF(unsigned long)
373 #if defined(BOOST_HAS_LONG_LONG)
374 BOOST_LCAST_DEF(boost::ulong_long_type)
375 BOOST_LCAST_DEF(boost::long_long_type )
376 #elif defined(BOOST_HAS_MS_INT64)
377 BOOST_LCAST_DEF(unsigned __int64)
378 BOOST_LCAST_DEF( __int64)
381 #undef BOOST_LCAST_DEF
382 #undef BOOST_LCAST_DEF1
384 #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
385 // Helper for floating point types.
386 // -1.23456789e-123456
390 // ^^^^^^^^ lcast_precision<Source>::value
393 // ^^^^^^ exponent (assumed 6 or less digits)
394 // sign + leading digit + decimal point + "e" + exponent sign == 5
395 template<class Source>
396 struct lcast_src_length_floating
399 std::numeric_limits<Source>::max_exponent10 <= 999999L &&
400 std::numeric_limits<Source>::min_exponent10 >= -999999L
402 BOOST_STATIC_CONSTANT(std::size_t, value =
403 5 + lcast_precision<Source>::value + 6
408 struct lcast_src_length<char,float>
409 : lcast_src_length_floating<float>
411 static void check_coverage() {}
415 struct lcast_src_length<char,double>
416 : lcast_src_length_floating<double>
418 static void check_coverage() {}
422 struct lcast_src_length<char,long double>
423 : lcast_src_length_floating<long double>
425 static void check_coverage() {}
428 #ifndef BOOST_LCAST_NO_WCHAR_T
430 struct lcast_src_length<wchar_t,float>
431 : lcast_src_length_floating<float>
433 static void check_coverage() {}
437 struct lcast_src_length<wchar_t,double>
438 : lcast_src_length_floating<double>
440 static void check_coverage() {}
444 struct lcast_src_length<wchar_t,long double>
445 : lcast_src_length_floating<long double>
447 static void check_coverage() {}
450 #endif // #ifndef BOOST_LCAST_NO_WCHAR_T
451 #endif // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
454 namespace detail // '0' and '-' constants
456 template<typename CharT> struct lcast_char_constants;
459 struct lcast_char_constants<char>
461 BOOST_STATIC_CONSTANT(char, zero = '0');
462 BOOST_STATIC_CONSTANT(char, minus = '-');
465 #ifndef BOOST_LCAST_NO_WCHAR_T
467 struct lcast_char_constants<wchar_t>
469 BOOST_STATIC_CONSTANT(wchar_t, zero = L'0');
470 BOOST_STATIC_CONSTANT(wchar_t, minus = L'-');
475 namespace detail // lexical_streambuf_fake
477 struct lexical_streambuf_fake
482 namespace detail // lcast_to_unsigned
484 #if (defined _MSC_VER)
485 # pragma warning( push )
486 // C4146: unary minus operator applied to unsigned type, result still unsigned
487 # pragma warning( disable : 4146 )
488 #elif defined( __BORLANDC__ )
489 # pragma option push -w-8041
493 BOOST_DEDUCED_TYPENAME make_unsigned<T>::type lcast_to_unsigned(T value)
495 typedef BOOST_DEDUCED_TYPENAME make_unsigned<T>::type result_type;
496 result_type uvalue = static_cast<result_type>(value);
497 return value < 0 ? -uvalue : uvalue;
499 #if (defined _MSC_VER)
500 # pragma warning( pop )
501 #elif defined( __BORLANDC__ )
506 namespace detail // lcast_put_unsigned
508 template<class Traits, class T, class CharT>
509 CharT* lcast_put_unsigned(T n, CharT* finish)
511 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
512 BOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_signed);
515 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
516 // TODO: use BOOST_NO_STD_LOCALE
518 typedef std::numpunct<CharT> numpunct;
519 numpunct const& np = BOOST_USE_FACET(numpunct, loc);
520 std::string const& grouping = np.grouping();
521 std::string::size_type const grouping_size = grouping.size();
522 CharT thousands_sep = grouping_size ? np.thousands_sep() : 0;
523 std::string::size_type group = 0; // current group number
524 char last_grp_size = grouping[0] <= 0 ? CHAR_MAX : grouping[0];
525 // a) Since grouping is const, grouping[grouping.size()] returns 0.
526 // b) It's safe to assume here and below that CHAR_MAX
527 // is equivalent to unlimited grouping:
528 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
529 BOOST_STATIC_ASSERT(std::numeric_limits<T>::digits10 < CHAR_MAX);
532 char left = last_grp_size;
535 typedef typename Traits::int_type int_type;
536 CharT const czero = lcast_char_constants<CharT>::zero;
537 int_type const zero = Traits::to_int_type(czero);
541 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
545 if(group < grouping_size)
547 char const grp_size = grouping[group];
548 last_grp_size = grp_size <= 0 ? CHAR_MAX : grp_size;
551 left = last_grp_size;
553 Traits::assign(*finish, thousands_sep);
560 int_type const digit = static_cast<int_type>(n % 10U);
561 Traits::assign(*finish, Traits::to_char_type(zero + digit));
569 namespace detail // stream wrapper for handling lexical conversions
571 template<typename Target, typename Source, typename Traits>
575 typedef typename widest_char<
576 typename stream_char<Target>::type,
577 typename stream_char<Source>::type>::type char_type;
579 typedef Traits traits_type;
582 lexical_stream(char_type* = 0, char_type* = 0)
584 stream.unsetf(std::ios::skipws);
585 lcast_set_precision(stream, static_cast<Source*>(0), static_cast<Target*>(0) );
589 #if defined(BOOST_NO_STRINGSTREAM)
590 stream.freeze(false);
593 bool operator<<(const Source &input)
595 return !(stream << input).fail();
597 template<typename InputStreamable>
598 bool operator>>(InputStreamable &output)
600 return !is_pointer<InputStreamable>::value &&
603 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
604 // GCC 2.9x lacks std::char_traits<>::eof().
605 // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
606 // configurations, which do provide std::char_traits<>::eof().
614 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
616 bool operator>>(std::string &output)
618 #if defined(BOOST_NO_STRINGSTREAM)
621 stream.str().swap(output);
624 #ifndef BOOST_LCAST_NO_WCHAR_T
625 bool operator>>(std::wstring &output)
627 stream.str().swap(output);
633 bool operator>>(std::basic_string<char_type,traits_type>& output)
635 stream.str().swap(output);
639 template<class Alloc>
640 bool operator>>(std::basic_string<char_type,traits_type,Alloc>& out)
642 std::basic_string<char_type,traits_type> str(stream.str());
643 out.assign(str.begin(), str.end());
648 #if defined(BOOST_NO_STRINGSTREAM)
649 std::strstream stream;
650 #elif defined(BOOST_NO_STD_LOCALE)
651 std::stringstream stream;
653 std::basic_stringstream<char_type,traits_type> stream;
658 namespace detail // optimized stream wrapper
660 // String representation of Source has an upper limit.
661 template< class CharT // a result of widest_char transformation
662 , class Base // lexical_streambuf_fake or basic_streambuf<CharT>
663 , class Traits // usually char_traits<CharT>
665 class lexical_stream_limited_src : public Base
667 // A string representation of Source is written to [start, finish).
668 // Currently, it is assumed that [start, finish) is big enough
669 // to hold a string representation of any Source value.
675 static void widen_and_assign(char*p, char ch)
677 Traits::assign(*p, ch);
680 #ifndef BOOST_LCAST_NO_WCHAR_T
681 static void widen_and_assign(wchar_t* p, char ch)
683 // TODO: use BOOST_NO_STD_LOCALE
685 wchar_t w = BOOST_USE_FACET(std::ctype<wchar_t>, loc).widen(ch);
686 Traits::assign(*p, w);
689 static void widen_and_assign(wchar_t* p, wchar_t ch)
691 Traits::assign(*p, ch);
694 static void widen_and_assign(char*, wchar_t ch); // undefined
697 template<class OutputStreamable>
698 bool lcast_put(const OutputStreamable& input)
700 this->setp(start, finish);
701 std::basic_ostream<CharT> stream(static_cast<Base*>(this));
702 lcast_set_precision(stream, static_cast<OutputStreamable*>(0));
703 bool const result = !(stream << input).fail();
704 finish = this->pptr();
709 lexical_stream_limited_src(lexical_stream_limited_src const&);
710 void operator=(lexical_stream_limited_src const&);
714 lexical_stream_limited_src(CharT* sta, CharT* fin)
721 template<class Alloc>
722 bool operator<<(std::basic_string<CharT,Traits,Alloc> const& str)
724 start = const_cast<CharT*>(str.data());
725 finish = start + str.length();
729 bool operator<<(bool);
730 bool operator<<(char);
731 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
732 bool operator<<(wchar_t);
734 bool operator<<(CharT const*);
735 bool operator<<(short);
736 bool operator<<(int);
737 bool operator<<(long);
738 bool operator<<(unsigned short);
739 bool operator<<(unsigned int);
740 bool operator<<(unsigned long);
741 #if defined(BOOST_HAS_LONG_LONG)
742 bool operator<<(boost::ulong_long_type);
743 bool operator<<(boost::long_long_type );
744 #elif defined(BOOST_HAS_MS_INT64)
745 bool operator<<(unsigned __int64);
746 bool operator<<( __int64);
748 // These three operators use ostream and streambuf.
749 // lcast_streambuf_for_source<T>::value is true.
750 bool operator<<(float);
751 bool operator<<(double);
752 bool operator<<(long double);
756 // Generic istream-based algorithm.
757 // lcast_streambuf_for_target<InputStreamable>::value is true.
758 template<typename InputStreamable>
759 bool operator>>(InputStreamable& output)
761 #if (defined _MSC_VER)
762 # pragma warning( push )
763 // conditional expression is constant
764 # pragma warning( disable : 4127 )
766 if(is_pointer<InputStreamable>::value)
769 this->setg(start, start, finish);
770 std::basic_istream<CharT> stream(static_cast<Base*>(this));
771 stream.unsetf(std::ios::skipws);
772 lcast_set_precision(stream, static_cast<InputStreamable*>(0));
773 #if (defined _MSC_VER)
774 # pragma warning( pop )
776 return stream >> output &&
778 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
779 // GCC 2.9x lacks std::char_traits<>::eof().
780 // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
781 // configurations, which do provide std::char_traits<>::eof().
789 bool operator>>(CharT&);
791 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
792 // This #if is in sync with lcast_streambuf_for_target
794 bool operator>>(std::string&);
796 #ifndef BOOST_LCAST_NO_WCHAR_T
797 bool operator>>(std::wstring&);
801 template<class Alloc>
802 bool operator>>(std::basic_string<CharT,Traits,Alloc>& str)
804 str.assign(start, finish);
810 template<typename CharT, class Base, class Traits>
811 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
814 typedef typename Traits::int_type int_type;
815 CharT const czero = lcast_char_constants<CharT>::zero;
816 int_type const zero = Traits::to_int_type(czero);
817 Traits::assign(*start, Traits::to_char_type(zero + value));
822 template<typename CharT, class Base, class Traits>
823 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
826 widen_and_assign(start, ch);
831 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
832 template<typename CharT, class Base, class Traits>
833 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
836 widen_and_assign(start, ch);
842 template<typename CharT, class Base, class Traits>
843 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
846 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
850 CharT const minus = lcast_char_constants<CharT>::minus;
851 Traits::assign(*start, minus);
856 template<typename CharT, class Base, class Traits>
857 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
860 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
864 CharT const minus = lcast_char_constants<CharT>::minus;
865 Traits::assign(*start, minus);
870 template<typename CharT, class Base, class Traits>
871 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
874 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
878 CharT const minus = lcast_char_constants<CharT>::minus;
879 Traits::assign(*start, minus);
884 #if defined(BOOST_HAS_LONG_LONG)
885 template<typename CharT, class Base, class Traits>
886 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
887 boost::long_long_type n)
889 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
893 CharT const minus = lcast_char_constants<CharT>::minus;
894 Traits::assign(*start, minus);
898 #elif defined(BOOST_HAS_MS_INT64)
899 template<typename CharT, class Base, class Traits>
900 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
903 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
907 CharT const minus = lcast_char_constants<CharT>::minus;
908 Traits::assign(*start, minus);
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 template<typename CharT, class Base, class Traits>
931 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
934 start = lcast_put_unsigned<Traits>(n, finish);
938 #if defined(BOOST_HAS_LONG_LONG)
939 template<typename CharT, class Base, class Traits>
940 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
941 boost::ulong_long_type n)
943 start = lcast_put_unsigned<Traits>(n, finish);
946 #elif defined(BOOST_HAS_MS_INT64)
947 template<typename CharT, class Base, class Traits>
948 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
951 start = lcast_put_unsigned<Traits>(n, finish);
956 template<typename CharT, class Base, class Traits>
957 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
960 return this->lcast_put(val);
963 template<typename CharT, class Base, class Traits>
964 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
967 return this->lcast_put(val);
970 template<typename CharT, class Base, class Traits>
971 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
974 return this->lcast_put(val);
977 template<typename CharT, class Base, class Traits>
978 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
981 start = const_cast<CharT*>(str);
982 finish = start + Traits::length(str);
986 template<typename CharT, class Base, class Traits>
987 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
990 bool const ok = (finish - start == 1);
992 Traits::assign(output, *start);
996 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
997 template<typename CharT, class Base, class Traits>
998 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
1001 str.assign(start, finish);
1005 #ifndef BOOST_LCAST_NO_WCHAR_T
1006 template<typename CharT, class Base, class Traits>
1007 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
1010 str.assign(start, finish);
1017 namespace detail // lcast_streambuf_for_source
1019 // Returns true if optimized stream wrapper needs ostream for writing.
1020 template<class Source>
1021 struct lcast_streambuf_for_source
1023 BOOST_STATIC_CONSTANT(bool, value = false);
1027 struct lcast_streambuf_for_source<float>
1029 BOOST_STATIC_CONSTANT(bool, value = true);
1033 struct lcast_streambuf_for_source<double>
1035 BOOST_STATIC_CONSTANT(bool, value = true);
1039 struct lcast_streambuf_for_source<long double>
1041 BOOST_STATIC_CONSTANT(bool, value = true);
1045 namespace detail // lcast_streambuf_for_target
1047 // Returns true if optimized stream wrapper needs istream for reading.
1048 template<class Target>
1049 struct lcast_streambuf_for_target
1051 BOOST_STATIC_CONSTANT(bool, value = true);
1055 struct lcast_streambuf_for_target<char>
1057 BOOST_STATIC_CONSTANT(bool, value = false);
1060 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
1062 struct lcast_streambuf_for_target<wchar_t>
1064 BOOST_STATIC_CONSTANT(bool, value = false);
1068 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1069 template<class Traits, class Alloc>
1070 struct lcast_streambuf_for_target<
1071 std::basic_string<char,Traits,Alloc> >
1073 BOOST_STATIC_CONSTANT(bool, value = false);
1076 #ifndef BOOST_LCAST_NO_WCHAR_T
1077 template<class Traits, class Alloc>
1078 struct lcast_streambuf_for_target<
1079 std::basic_string<wchar_t,Traits,Alloc> >
1081 BOOST_STATIC_CONSTANT(bool, value = false);
1086 struct lcast_streambuf_for_target<std::string>
1088 BOOST_STATIC_CONSTANT(bool, value = false);
1091 #ifndef BOOST_LCAST_NO_WCHAR_T
1093 struct lcast_streambuf_for_target<std::wstring>
1095 BOOST_STATIC_CONSTANT(bool, value = false);
1101 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1103 // call-by-const reference version
1108 struct array_to_pointer_decay
1113 template<class T, std::size_t N>
1114 struct array_to_pointer_decay<T[N]>
1116 typedef const T * type;
1119 #if (defined _MSC_VER)
1120 # pragma warning( push )
1121 # pragma warning( disable : 4701 ) // possible use of ... before initialization
1122 # pragma warning( disable : 4702 ) // unreachable code
1125 template< typename Target
1127 , bool Unlimited // string representation of Source is unlimited
1130 Target lexical_cast(
1131 BOOST_DEDUCED_TYPENAME boost::call_traits<Source>::param_type arg,
1132 CharT* buf, std::size_t src_len)
1134 typedef BOOST_DEDUCED_TYPENAME
1135 deduce_char_traits<CharT,Target,Source>::type traits;
1137 typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
1138 lcast_streambuf_for_target<Target>::value ||
1139 lcast_streambuf_for_source<Source>::value
1140 , std::basic_streambuf<CharT>
1141 , lexical_streambuf_fake
1144 BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
1146 , detail::lexical_stream<Target,Source,traits>
1147 , detail::lexical_stream_limited_src<CharT,base,traits>
1148 >::type interpreter(buf, buf + src_len);
1151 if(!(interpreter << arg && interpreter >> result))
1152 BOOST_LCAST_THROW_BAD_CAST(Source, Target);
1155 #if (defined _MSC_VER)
1156 # pragma warning( pop )
1160 template<typename Target, typename Source>
1161 inline Target lexical_cast(const Source &arg)
1163 typedef typename detail::array_to_pointer_decay<Source>::type src;
1165 typedef typename detail::widest_char<
1166 typename detail::stream_char<Target>::type
1167 , typename detail::stream_char<src>::type
1170 typedef detail::lcast_src_length<char_type, src> lcast_src_length;
1171 std::size_t const src_len = lcast_src_length::value;
1172 char_type buf[src_len + 1];
1173 lcast_src_length::check_coverage();
1174 return detail::lexical_cast<Target, src, !src_len>(arg, buf, src_len);
1179 // call-by-value fallback version (deprecated)
1181 template<typename Target, typename Source>
1182 Target lexical_cast(Source arg)
1184 typedef typename detail::widest_char<
1185 BOOST_DEDUCED_TYPENAME detail::stream_char<Target>::type
1186 , BOOST_DEDUCED_TYPENAME detail::stream_char<Source>::type
1189 typedef std::char_traits<char_type> traits;
1190 detail::lexical_stream<Target, Source, traits> interpreter;
1193 if(!(interpreter << arg && interpreter >> result))
1194 #ifndef BOOST_NO_TYPEID
1195 throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)));
1197 throw_exception(bad_lexical_cast());
1205 // Copyright Kevlin Henney, 2000-2005.
1206 // Copyright Alexander Nasonov, 2006-2007.
1208 // Distributed under the Boost Software License, Version 1.0. (See
1209 // accompanying file LICENSE_1_0.txt or copy at
1210 // http://www.boost.org/LICENSE_1_0.txt)
1212 #undef BOOST_LCAST_NO_WCHAR_T