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) || \
45 defined(BOOST_NO_STD_WSTRING) || \
46 defined(BOOST_NO_STD_LOCALE)
47 #define BOOST_LCAST_NO_WCHAR_T
52 // exception used to indicate runtime lexical_cast failure
53 class bad_lexical_cast
: public std::bad_cast
55 #if defined(__BORLANDC__) && BOOST_WORKAROUND( __BORLANDC__, < 0x560 )
56 // under bcc32 5.5.1 bad_cast doesn't derive from exception
57 , public std::exception
63 #ifndef BOOST_NO_TYPEID
64 source(&typeid(void)), target(&typeid(void))
66 source(0), target(0) // this breaks getters
72 const std::type_info
&source_type_arg
,
73 const std::type_info
&target_type_arg
) :
74 source(&source_type_arg
), target(&target_type_arg
)
78 const std::type_info
&source_type() const
82 const std::type_info
&target_type() const
87 virtual const char *what() const throw()
89 return "bad lexical cast: "
90 "source type value could not be interpreted as target";
92 virtual ~bad_lexical_cast() throw()
96 const std::type_info
*source
;
97 const std::type_info
*target
;
100 namespace detail
// selectors for choosing stream character type
102 template<typename Type
>
108 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
109 template<class CharT
, class Traits
, class Alloc
>
110 struct stream_char
< std::basic_string
<CharT
,Traits
,Alloc
> >
116 #ifndef BOOST_LCAST_NO_WCHAR_T
117 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
119 struct stream_char
<wchar_t>
121 typedef wchar_t type
;
126 struct stream_char
<wchar_t *>
128 typedef wchar_t type
;
132 struct stream_char
<const wchar_t *>
134 typedef wchar_t type
;
137 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
139 struct stream_char
<std::wstring
>
141 typedef wchar_t type
;
146 template<typename TargetChar
, typename SourceChar
>
149 typedef TargetChar type
;
153 struct widest_char
<char, wchar_t>
155 typedef wchar_t type
;
159 namespace detail
// deduce_char_traits template
161 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
162 template<class CharT
, class Target
, class Source
>
163 struct deduce_char_traits
165 typedef std::char_traits
<CharT
> type
;
168 template<class CharT
, class Traits
, class Alloc
, class Source
>
169 struct deduce_char_traits
< CharT
170 , std::basic_string
<CharT
,Traits
,Alloc
>
177 template<class CharT
, class Target
, class Traits
, class Alloc
>
178 struct deduce_char_traits
< CharT
180 , std::basic_string
<CharT
,Traits
,Alloc
>
186 template<class CharT
, class Traits
, class Alloc1
, class Alloc2
>
187 struct deduce_char_traits
< CharT
188 , std::basic_string
<CharT
,Traits
,Alloc1
>
189 , std::basic_string
<CharT
,Traits
,Alloc2
>
197 namespace detail
// lcast_src_length
199 // Return max. length of string representation of Source;
200 // 0 if unlimited (with exceptions for some types, see below).
201 // Values with limited string representation are placed to
202 // the buffer locally defined in lexical_cast function.
203 // 1 is returned for few types such as CharT const* or
204 // std::basic_string<CharT> that already have an internal
205 // buffer ready to be reused by lexical_stream_limited_src.
206 // Each specialization should have a correspondent operator<<
207 // defined in lexical_stream_limited_src.
208 template< class CharT
// A result of widest_char transformation.
209 , class Source
// Source type of lexical_cast.
211 struct lcast_src_length
213 BOOST_STATIC_CONSTANT(std::size_t, value
= 0);
214 // To check coverage, build the test with
215 // bjam --v2 profile optimization=off
216 static void check_coverage() {}
220 struct lcast_src_length
<char, bool>
222 BOOST_STATIC_CONSTANT(std::size_t, value
= 1);
223 static void check_coverage() {}
227 struct lcast_src_length
<char, char>
229 BOOST_STATIC_CONSTANT(std::size_t, value
= 1);
230 static void check_coverage() {}
233 // No specializations for:
234 // lcast_src_length<char, signed char>
235 // lcast_src_length<char, unsigned char>
236 // lcast_src_length<char, signed char*>
237 // lcast_src_length<char, unsigned char*>
238 // lcast_src_length<char, signed char const*>
239 // lcast_src_length<char, unsigned char const*>
241 #ifndef BOOST_LCAST_NO_WCHAR_T
243 struct lcast_src_length
<wchar_t, bool>
245 BOOST_STATIC_CONSTANT(std::size_t, value
= 1);
246 static void check_coverage() {}
250 struct lcast_src_length
<wchar_t, char>
252 BOOST_STATIC_CONSTANT(std::size_t, value
= 1);
253 static void check_coverage() {}
256 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
258 struct lcast_src_length
<wchar_t, wchar_t>
260 BOOST_STATIC_CONSTANT(std::size_t, value
= 1);
261 static void check_coverage() {}
267 struct lcast_src_length
<char, char const*>
269 BOOST_STATIC_CONSTANT(std::size_t, value
= 1);
270 static void check_coverage() {}
274 struct lcast_src_length
<char, char*>
276 BOOST_STATIC_CONSTANT(std::size_t, value
= 1);
277 static void check_coverage() {}
280 #ifndef BOOST_LCAST_NO_WCHAR_T
282 struct lcast_src_length
<wchar_t, wchar_t const*>
284 BOOST_STATIC_CONSTANT(std::size_t, value
= 1);
285 static void check_coverage() {}
289 struct lcast_src_length
<wchar_t, wchar_t*>
291 BOOST_STATIC_CONSTANT(std::size_t, value
= 1);
292 static void check_coverage() {}
296 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
297 template<class CharT
, class Traits
, class Alloc
>
298 struct lcast_src_length
< CharT
, std::basic_string
<CharT
,Traits
,Alloc
> >
300 BOOST_STATIC_CONSTANT(std::size_t, value
= 1);
301 static void check_coverage() {}
305 struct lcast_src_length
< char, std::basic_string
<char> >
307 BOOST_STATIC_CONSTANT(std::size_t, value
= 1);
308 static void check_coverage() {}
311 #ifndef BOOST_LCAST_NO_WCHAR_T
313 struct lcast_src_length
< wchar_t, std::basic_string
<wchar_t> >
315 BOOST_STATIC_CONSTANT(std::size_t, value
= 1);
316 static void check_coverage() {}
321 // Helper for integral types.
322 // Notes on length calculation:
323 // Max length for 32bit int with grouping "\1" and thousands_sep ',':
324 // "-2,1,4,7,4,8,3,6,4,7"
326 // ^ - 1 digit not counted by digits10
327 // ^^^^^^^^^^^^^^^^^^ - digits10 * 2
329 // Constant is_specialized is used instead of constant 1
330 // to prevent buffer overflow in a rare case when
331 // <boost/limits.hpp> doesn't add missing specialization for
332 // numeric_limits<T> for some integral type T.
333 // When is_specialized is false, the whole expression is 0.
334 template<class Source
>
335 struct lcast_src_length_integral
337 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
338 BOOST_STATIC_CONSTANT(std::size_t, value
=
339 std::numeric_limits
<Source
>::is_signed
+
340 std::numeric_limits
<Source
>::is_specialized
+ // == 1
341 std::numeric_limits
<Source
>::digits10
* 2
344 BOOST_STATIC_CONSTANT(std::size_t, value
= 156);
345 BOOST_STATIC_ASSERT(sizeof(Source
) * CHAR_BIT
<= 256);
349 #define BOOST_LCAST_DEF1(CharT, T) \
350 template<> struct lcast_src_length<CharT, T> \
351 : lcast_src_length_integral<T> \
352 { static void check_coverage() {} };
354 #ifdef BOOST_LCAST_NO_WCHAR_T
355 #define BOOST_LCAST_DEF(T) BOOST_LCAST_DEF1(char, T)
357 #define BOOST_LCAST_DEF(T) \
358 BOOST_LCAST_DEF1(char, T) \
359 BOOST_LCAST_DEF1(wchar_t, T)
362 BOOST_LCAST_DEF(short)
363 BOOST_LCAST_DEF(unsigned short)
365 BOOST_LCAST_DEF(unsigned int)
366 BOOST_LCAST_DEF(long)
367 BOOST_LCAST_DEF(unsigned long)
368 #if defined(BOOST_HAS_LONG_LONG)
369 BOOST_LCAST_DEF(boost::ulong_long_type
)
370 BOOST_LCAST_DEF(boost::long_long_type
)
371 #elif defined(BOOST_HAS_MS_INT64)
372 BOOST_LCAST_DEF(unsigned __int64
)
373 BOOST_LCAST_DEF( __int64
)
376 #undef BOOST_LCAST_DEF
377 #undef BOOST_LCAST_DEF1
379 #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
380 // Helper for floating point types.
381 // -1.23456789e-123456
385 // ^^^^^^^^ lcast_precision<Source>::value
388 // ^^^^^^ exponent (assumed 6 or less digits)
389 // sign + leading digit + decimal point + "e" + exponent sign == 5
390 template<class Source
>
391 struct lcast_src_length_floating
394 std::numeric_limits
<Source
>::max_exponent10
<= 999999L &&
395 std::numeric_limits
<Source
>::min_exponent10
>= -999999L
397 BOOST_STATIC_CONSTANT(std::size_t, value
=
398 5 + lcast_precision
<Source
>::value
+ 6
403 struct lcast_src_length
<char,float>
404 : lcast_src_length_floating
<float>
406 static void check_coverage() {}
410 struct lcast_src_length
<char,double>
411 : lcast_src_length_floating
<double>
413 static void check_coverage() {}
417 struct lcast_src_length
<char,long double>
418 : lcast_src_length_floating
<long double>
420 static void check_coverage() {}
423 #ifndef BOOST_LCAST_NO_WCHAR_T
425 struct lcast_src_length
<wchar_t,float>
426 : lcast_src_length_floating
<float>
428 static void check_coverage() {}
432 struct lcast_src_length
<wchar_t,double>
433 : lcast_src_length_floating
<double>
435 static void check_coverage() {}
439 struct lcast_src_length
<wchar_t,long double>
440 : lcast_src_length_floating
<long double>
442 static void check_coverage() {}
445 #endif // #ifndef BOOST_LCAST_NO_WCHAR_T
446 #endif // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
449 namespace detail
// '0' and '-' constants
451 template<typename CharT
> struct lcast_char_constants
;
454 struct lcast_char_constants
<char>
456 BOOST_STATIC_CONSTANT(char, zero
= '0');
457 BOOST_STATIC_CONSTANT(char, minus
= '-');
460 #ifndef BOOST_LCAST_NO_WCHAR_T
462 struct lcast_char_constants
<wchar_t>
464 BOOST_STATIC_CONSTANT(wchar_t, zero
= L
'0');
465 BOOST_STATIC_CONSTANT(wchar_t, minus
= L
'-');
470 namespace detail
// lexical_streambuf_fake
472 struct lexical_streambuf_fake
477 namespace detail
// lcast_to_unsigned
479 #if (defined _MSC_VER)
480 # pragma warning( push )
481 // C4146: unary minus operator applied to unsigned type, result still unsigned
482 # pragma warning( disable : 4146 )
483 #elif defined( __BORLANDC__ )
484 # pragma option push -w-8041
488 BOOST_DEDUCED_TYPENAME make_unsigned
<T
>::type
lcast_to_unsigned(T value
)
490 typedef BOOST_DEDUCED_TYPENAME make_unsigned
<T
>::type result_type
;
491 result_type uvalue
= static_cast<result_type
>(value
);
492 return value
< 0 ? -uvalue
: uvalue
;
494 #if (defined _MSC_VER)
495 # pragma warning( pop )
496 #elif defined( __BORLANDC__ )
501 namespace detail
// lcast_put_unsigned
503 template<class Traits
, class T
, class CharT
>
504 CharT
* lcast_put_unsigned(T n
, CharT
* finish
)
506 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
507 BOOST_STATIC_ASSERT(!std::numeric_limits
<T
>::is_signed
);
510 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
511 // TODO: use BOOST_NO_STD_LOCALE
513 typedef std::numpunct
<CharT
> numpunct
;
514 numpunct
const& np
= BOOST_USE_FACET(numpunct
, loc
);
515 std::string
const& grouping
= np
.grouping();
516 std::string::size_type
const grouping_size
= grouping
.size();
517 CharT thousands_sep
= grouping_size
? np
.thousands_sep() : 0;
518 std::string::size_type group
= 0; // current group number
519 char last_grp_size
= grouping
[0] <= 0 ? CHAR_MAX
: grouping
[0];
520 // a) Since grouping is const, grouping[grouping.size()] returns 0.
521 // b) It's safe to assume here and below that CHAR_MAX
522 // is equivalent to unlimited grouping:
523 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
524 BOOST_STATIC_ASSERT(std::numeric_limits
<T
>::digits10
< CHAR_MAX
);
527 char left
= last_grp_size
;
530 typedef typename
Traits::int_type int_type
;
531 CharT
const czero
= lcast_char_constants
<CharT
>::zero
;
532 int_type
const zero
= Traits::to_int_type(czero
);
536 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
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
);
555 int_type
const digit
= static_cast<int_type
>(n
% 10U);
556 Traits::assign(*finish
, Traits::to_char_type(zero
+ digit
));
564 namespace detail
// stream wrapper for handling lexical conversions
566 template<typename Target
, typename Source
, typename Traits
>
570 typedef typename widest_char
<
571 typename stream_char
<Target
>::type
,
572 typename stream_char
<Source
>::type
>::type char_type
;
574 typedef Traits traits_type
;
577 lexical_stream(char_type
* = 0, char_type
* = 0)
579 stream
.unsetf(std::ios::skipws
);
580 lcast_set_precision(stream
, (Source
*)0, (Target
*)0);
584 #if defined(BOOST_NO_STRINGSTREAM)
585 stream
.freeze(false);
588 bool operator<<(const Source
&input
)
590 return !(stream
<< input
).fail();
592 template<typename InputStreamable
>
593 bool operator>>(InputStreamable
&output
)
595 return !is_pointer
<InputStreamable
>::value
&&
598 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
599 // GCC 2.9x lacks std::char_traits<>::eof().
600 // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
601 // configurations, which do provide std::char_traits<>::eof().
609 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
611 bool operator>>(std::string
&output
)
613 #if defined(BOOST_NO_STRINGSTREAM)
616 stream
.str().swap(output
);
619 #ifndef BOOST_LCAST_NO_WCHAR_T
620 bool operator>>(std::wstring
&output
)
622 stream
.str().swap(output
);
628 bool operator>>(std::basic_string
<char_type
,traits_type
>& output
)
630 stream
.str().swap(output
);
634 template<class Alloc
>
635 bool operator>>(std::basic_string
<char_type
,traits_type
,Alloc
>& out
)
637 std::basic_string
<char_type
,traits_type
> str(stream
.str());
638 out
.assign(str
.begin(), str
.end());
643 #if defined(BOOST_NO_STRINGSTREAM)
644 std::strstream stream
;
645 #elif defined(BOOST_NO_STD_LOCALE)
646 std::stringstream stream
;
648 std::basic_stringstream
<char_type
,traits_type
> stream
;
653 namespace detail
// optimized stream wrapper
655 // String representation of Source has an upper limit.
656 template< class CharT
// a result of widest_char transformation
657 , class Base
// lexical_streambuf_fake or basic_streambuf<CharT>
658 , class Traits
// usually char_traits<CharT>
660 class lexical_stream_limited_src
: public Base
662 // A string representation of Source is written to [start, finish).
663 // Currently, it is assumed that [start, finish) is big enough
664 // to hold a string representation of any Source value.
670 static void widen_and_assign(char*p
, char ch
)
672 Traits::assign(*p
, ch
);
675 #ifndef BOOST_LCAST_NO_WCHAR_T
676 static void widen_and_assign(wchar_t* p
, char ch
)
678 // TODO: use BOOST_NO_STD_LOCALE
680 wchar_t w
= BOOST_USE_FACET(std::ctype
<wchar_t>, loc
).widen(ch
);
681 Traits::assign(*p
, w
);
684 static void widen_and_assign(wchar_t* p
, wchar_t ch
)
686 Traits::assign(*p
, ch
);
689 static void widen_and_assign(char*, wchar_t ch
); // undefined
692 template<class OutputStreamable
>
693 bool lcast_put(const OutputStreamable
& input
)
695 this->setp(start
, finish
);
696 std::basic_ostream
<CharT
> stream(static_cast<Base
*>(this));
697 lcast_set_precision(stream
, (OutputStreamable
*)0);
698 bool const result
= !(stream
<< input
).fail();
699 finish
= this->pptr();
704 lexical_stream_limited_src(lexical_stream_limited_src
const&);
705 void operator=(lexical_stream_limited_src
const&);
709 lexical_stream_limited_src(CharT
* sta
, CharT
* fin
)
716 template<class Alloc
>
717 bool operator<<(std::basic_string
<CharT
,Traits
,Alloc
> const& str
)
719 start
= const_cast<CharT
*>(str
.data());
720 finish
= start
+ str
.length();
724 bool operator<<(bool);
725 bool operator<<(char);
726 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
727 bool operator<<(wchar_t);
729 bool operator<<(CharT
const*);
730 bool operator<<(short);
731 bool operator<<(int);
732 bool operator<<(long);
733 bool operator<<(unsigned short);
734 bool operator<<(unsigned int);
735 bool operator<<(unsigned long);
736 #if defined(BOOST_HAS_LONG_LONG)
737 bool operator<<(boost::ulong_long_type
);
738 bool operator<<(boost::long_long_type
);
739 #elif defined(BOOST_HAS_MS_INT64)
740 bool operator<<(unsigned __int64
);
741 bool operator<<( __int64
);
743 // These three operators use ostream and streambuf.
744 // lcast_streambuf_for_source<T>::value is true.
745 bool operator<<(float);
746 bool operator<<(double);
747 bool operator<<(long double);
751 // Generic istream-based algorithm.
752 // lcast_streambuf_for_target<InputStreamable>::value is true.
753 template<typename InputStreamable
>
754 bool operator>>(InputStreamable
& output
)
756 #if (defined _MSC_VER)
757 # pragma warning( push )
758 // conditional expression is constant
759 # pragma warning( disable : 4127 )
761 if(is_pointer
<InputStreamable
>::value
)
764 this->setg(start
, start
, finish
);
765 std::basic_istream
<CharT
> stream(static_cast<Base
*>(this));
766 stream
.unsetf(std::ios::skipws
);
767 lcast_set_precision(stream
, (InputStreamable
*)0);
768 #if (defined _MSC_VER)
769 # pragma warning( pop )
771 return stream
>> output
&&
773 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
774 // GCC 2.9x lacks std::char_traits<>::eof().
775 // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
776 // configurations, which do provide std::char_traits<>::eof().
784 bool operator>>(CharT
&);
786 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
787 // This #if is in sync with lcast_streambuf_for_target
789 bool operator>>(std::string
&);
791 #ifndef BOOST_LCAST_NO_WCHAR_T
792 bool operator>>(std::wstring
&);
796 template<class Alloc
>
797 bool operator>>(std::basic_string
<CharT
,Traits
,Alloc
>& str
)
799 str
.assign(start
, finish
);
805 template<typename CharT
, class Base
, class Traits
>
806 inline bool lexical_stream_limited_src
<CharT
,Base
,Traits
>::operator<<(
809 typedef typename
Traits::int_type int_type
;
810 CharT
const czero
= lcast_char_constants
<CharT
>::zero
;
811 int_type
const zero
= Traits::to_int_type(czero
);
812 Traits::assign(*start
, Traits::to_char_type(zero
+ value
));
817 template<typename CharT
, class Base
, class Traits
>
818 inline bool lexical_stream_limited_src
<CharT
,Base
,Traits
>::operator<<(
821 widen_and_assign(start
, ch
);
826 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
827 template<typename CharT
, class Base
, class Traits
>
828 inline bool lexical_stream_limited_src
<CharT
,Base
,Traits
>::operator<<(
831 widen_and_assign(start
, ch
);
837 template<typename CharT
, class Base
, class Traits
>
838 inline bool lexical_stream_limited_src
<CharT
,Base
,Traits
>::operator<<(
841 start
= lcast_put_unsigned
<Traits
>(lcast_to_unsigned(n
), finish
);
845 CharT
const minus
= lcast_char_constants
<CharT
>::minus
;
846 Traits::assign(*start
, minus
);
851 template<typename CharT
, class Base
, class Traits
>
852 inline bool lexical_stream_limited_src
<CharT
,Base
,Traits
>::operator<<(
855 start
= lcast_put_unsigned
<Traits
>(lcast_to_unsigned(n
), finish
);
859 CharT
const minus
= lcast_char_constants
<CharT
>::minus
;
860 Traits::assign(*start
, minus
);
865 template<typename CharT
, class Base
, class Traits
>
866 inline bool lexical_stream_limited_src
<CharT
,Base
,Traits
>::operator<<(
869 start
= lcast_put_unsigned
<Traits
>(lcast_to_unsigned(n
), finish
);
873 CharT
const minus
= lcast_char_constants
<CharT
>::minus
;
874 Traits::assign(*start
, minus
);
879 #if defined(BOOST_HAS_LONG_LONG)
880 template<typename CharT
, class Base
, class Traits
>
881 inline bool lexical_stream_limited_src
<CharT
,Base
,Traits
>::operator<<(
882 boost::long_long_type n
)
884 start
= lcast_put_unsigned
<Traits
>(lcast_to_unsigned(n
), finish
);
888 CharT
const minus
= lcast_char_constants
<CharT
>::minus
;
889 Traits::assign(*start
, minus
);
893 #elif defined(BOOST_HAS_MS_INT64)
894 template<typename CharT
, class Base
, class Traits
>
895 inline bool lexical_stream_limited_src
<CharT
,Base
,Traits
>::operator<<(
898 start
= lcast_put_unsigned
<Traits
>(lcast_to_unsigned(n
), finish
);
902 CharT
const minus
= lcast_char_constants
<CharT
>::minus
;
903 Traits::assign(*start
, minus
);
909 template<typename CharT
, class Base
, class Traits
>
910 inline bool lexical_stream_limited_src
<CharT
,Base
,Traits
>::operator<<(
913 start
= lcast_put_unsigned
<Traits
>(n
, finish
);
917 template<typename CharT
, class Base
, class Traits
>
918 inline bool lexical_stream_limited_src
<CharT
,Base
,Traits
>::operator<<(
921 start
= lcast_put_unsigned
<Traits
>(n
, finish
);
925 template<typename CharT
, class Base
, class Traits
>
926 inline bool lexical_stream_limited_src
<CharT
,Base
,Traits
>::operator<<(
929 start
= lcast_put_unsigned
<Traits
>(n
, finish
);
933 #if defined(BOOST_HAS_LONG_LONG)
934 template<typename CharT
, class Base
, class Traits
>
935 inline bool lexical_stream_limited_src
<CharT
,Base
,Traits
>::operator<<(
936 boost::ulong_long_type n
)
938 start
= lcast_put_unsigned
<Traits
>(n
, finish
);
941 #elif defined(BOOST_HAS_MS_INT64)
942 template<typename CharT
, class Base
, class Traits
>
943 inline bool lexical_stream_limited_src
<CharT
,Base
,Traits
>::operator<<(
946 start
= lcast_put_unsigned
<Traits
>(n
, finish
);
951 template<typename CharT
, class Base
, class Traits
>
952 inline bool lexical_stream_limited_src
<CharT
,Base
,Traits
>::operator<<(
955 return this->lcast_put(val
);
958 template<typename CharT
, class Base
, class Traits
>
959 inline bool lexical_stream_limited_src
<CharT
,Base
,Traits
>::operator<<(
962 return this->lcast_put(val
);
965 template<typename CharT
, class Base
, class Traits
>
966 inline bool lexical_stream_limited_src
<CharT
,Base
,Traits
>::operator<<(
969 return this->lcast_put(val
);
972 template<typename CharT
, class Base
, class Traits
>
973 inline bool lexical_stream_limited_src
<CharT
,Base
,Traits
>::operator<<(
976 start
= const_cast<CharT
*>(str
);
977 finish
= start
+ Traits::length(str
);
981 template<typename CharT
, class Base
, class Traits
>
982 inline bool lexical_stream_limited_src
<CharT
,Base
,Traits
>::operator>>(
985 bool const ok
= (finish
- start
== 1);
987 Traits::assign(output
, *start
);
991 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
992 template<typename CharT
, class Base
, class Traits
>
993 inline bool lexical_stream_limited_src
<CharT
,Base
,Traits
>::operator>>(
996 str
.assign(start
, finish
);
1000 #ifndef BOOST_LCAST_NO_WCHAR_T
1001 template<typename CharT
, class Base
, class Traits
>
1002 inline bool lexical_stream_limited_src
<CharT
,Base
,Traits
>::operator>>(
1005 str
.assign(start
, finish
);
1012 namespace detail
// lcast_streambuf_for_source
1014 // Returns true if optimized stream wrapper needs ostream for writing.
1015 template<class Source
>
1016 struct lcast_streambuf_for_source
1018 BOOST_STATIC_CONSTANT(bool, value
= false);
1022 struct lcast_streambuf_for_source
<float>
1024 BOOST_STATIC_CONSTANT(bool, value
= true);
1028 struct lcast_streambuf_for_source
<double>
1030 BOOST_STATIC_CONSTANT(bool, value
= true);
1034 struct lcast_streambuf_for_source
<long double>
1036 BOOST_STATIC_CONSTANT(bool, value
= true);
1040 namespace detail
// lcast_streambuf_for_target
1042 // Returns true if optimized stream wrapper needs istream for reading.
1043 template<class Target
>
1044 struct lcast_streambuf_for_target
1046 BOOST_STATIC_CONSTANT(bool, value
= true);
1050 struct lcast_streambuf_for_target
<char>
1052 BOOST_STATIC_CONSTANT(bool, value
= false);
1055 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
1057 struct lcast_streambuf_for_target
<wchar_t>
1059 BOOST_STATIC_CONSTANT(bool, value
= false);
1063 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1064 template<class Traits
, class Alloc
>
1065 struct lcast_streambuf_for_target
<
1066 std::basic_string
<char,Traits
,Alloc
> >
1068 BOOST_STATIC_CONSTANT(bool, value
= false);
1071 #ifndef BOOST_LCAST_NO_WCHAR_T
1072 template<class Traits
, class Alloc
>
1073 struct lcast_streambuf_for_target
<
1074 std::basic_string
<wchar_t,Traits
,Alloc
> >
1076 BOOST_STATIC_CONSTANT(bool, value
= false);
1081 struct lcast_streambuf_for_target
<std::string
>
1083 BOOST_STATIC_CONSTANT(bool, value
= false);
1086 #ifndef BOOST_LCAST_NO_WCHAR_T
1088 struct lcast_streambuf_for_target
<std::wstring
>
1090 BOOST_STATIC_CONSTANT(bool, value
= false);
1096 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1098 // call-by-const reference version
1103 struct array_to_pointer_decay
1108 template<class T
, std::size_t N
>
1109 struct array_to_pointer_decay
<T
[N
]>
1111 typedef const T
* type
;
1114 template< typename Target
1116 , bool Unlimited
// string representation of Source is unlimited
1119 Target
lexical_cast(
1120 BOOST_DEDUCED_TYPENAME
boost::call_traits
<Source
>::param_type arg
,
1121 CharT
* buf
, std::size_t src_len
)
1123 typedef BOOST_DEDUCED_TYPENAME
1124 deduce_char_traits
<CharT
,Target
,Source
>::type traits
;
1126 typedef BOOST_DEDUCED_TYPENAME
boost::mpl::if_c
<
1127 lcast_streambuf_for_target
<Target
>::value
||
1128 lcast_streambuf_for_source
<Source
>::value
1129 , std::basic_streambuf
<CharT
>
1130 , lexical_streambuf_fake
1133 BOOST_DEDUCED_TYPENAME
boost::mpl::if_c
<
1135 , detail::lexical_stream
<Target
,Source
,traits
>
1136 , detail::lexical_stream_limited_src
<CharT
,base
,traits
>
1137 >::type
interpreter(buf
, buf
+ src_len
);
1139 // The original form, reproduced below, is more elegant
1140 // but yields a spurious C4701 warning ("possible use of
1141 // "result" before initialization") with VC7.1 (/W4).
1145 // if(!(interpreter << arg && interpreter >> result))
1146 // throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)));
1149 if(interpreter
<< arg
) {
1151 if (interpreter
>> result
)
1154 #ifndef BOOST_NO_TYPEID
1155 throw_exception(bad_lexical_cast(typeid(Source
), typeid(Target
)));
1157 throw_exception(bad_lexical_cast());
1159 return Target(); // normally never reached (throw_exception)
1163 template<typename Target
, typename Source
>
1164 inline Target
lexical_cast(const Source
&arg
)
1166 typedef typename
detail::array_to_pointer_decay
<Source
>::type src
;
1168 typedef typename
detail::widest_char
<
1169 typename
detail::stream_char
<Target
>::type
1170 , typename
detail::stream_char
<src
>::type
1173 typedef detail::lcast_src_length
<char_type
, src
> lcast_src_length
;
1174 std::size_t const src_len
= lcast_src_length::value
;
1175 char_type buf
[src_len
+ 1];
1176 lcast_src_length::check_coverage();
1177 return detail::lexical_cast
<Target
, src
, !src_len
>(arg
, buf
, src_len
);
1182 // call-by-value fallback version (deprecated)
1184 template<typename Target
, typename Source
>
1185 Target
lexical_cast(Source arg
)
1187 typedef typename
detail::widest_char
<
1188 BOOST_DEDUCED_TYPENAME
detail::stream_char
<Target
>::type
1189 , BOOST_DEDUCED_TYPENAME
detail::stream_char
<Source
>::type
1192 typedef std::char_traits
<char_type
> traits
;
1193 detail::lexical_stream
<Target
, Source
, traits
> interpreter
;
1196 if(!(interpreter
<< arg
&& interpreter
>> result
))
1197 #ifndef BOOST_NO_TYPEID
1198 throw_exception(bad_lexical_cast(typeid(Source
), typeid(Target
)));
1200 throw_exception(bad_lexical_cast());
1208 // Copyright Kevlin Henney, 2000-2005.
1209 // Copyright Alexander Nasonov, 2006-2007.
1211 // Distributed under the Boost Software License, Version 1.0. (See
1212 // accompanying file LICENSE_1_0.txt or copy at
1213 // http://www.boost.org/LICENSE_1_0.txt)
1215 #undef BOOST_LCAST_NO_WCHAR_T