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, Antony Polukhin and other Boosters
15 // when: November 2000, March 2003, June 2005, June 2006, March 2011
24 #include <boost/config.hpp>
25 #include <boost/limits.hpp>
26 #include <boost/mpl/if.hpp>
27 #include <boost/throw_exception.hpp>
28 #include <boost/type_traits/is_pointer.hpp>
29 #include <boost/type_traits/is_integral.hpp>
30 #include <boost/type_traits/is_arithmetic.hpp>
31 #include <boost/numeric/conversion/cast.hpp>
32 #include <boost/type_traits/ice.hpp>
33 #include <boost/type_traits/make_unsigned.hpp>
34 #include <boost/type_traits/is_signed.hpp>
35 #include <boost/call_traits.hpp>
36 #include <boost/static_assert.hpp>
37 #include <boost/detail/lcast_precision.hpp>
38 #include <boost/detail/workaround.hpp>
40 #ifndef BOOST_NO_STD_LOCALE
44 #ifdef BOOST_NO_STRINGSTREAM
50 #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
51 #define BOOST_LCAST_NO_WCHAR_T
54 #ifdef BOOST_NO_TYPEID
55 #define BOOST_LCAST_THROW_BAD_CAST(S, T) throw_exception(bad_lexical_cast())
57 #define BOOST_LCAST_THROW_BAD_CAST(Source, Target) \
58 throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)))
63 // exception used to indicate runtime lexical_cast failure
64 class bad_lexical_cast :
65 // workaround MSVC bug with std::bad_cast when _HAS_EXCEPTIONS == 0
66 #if defined(BOOST_MSVC) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS
72 #if defined(__BORLANDC__) && BOOST_WORKAROUND( __BORLANDC__, < 0x560 )
73 // under bcc32 5.5.1 bad_cast doesn't derive from exception
74 , public std::exception
80 #ifndef BOOST_NO_TYPEID
81 source(&typeid(void)), target(&typeid(void))
83 source(0), target(0) // this breaks getters
89 const std::type_info &source_type_arg,
90 const std::type_info &target_type_arg) :
91 source(&source_type_arg), target(&target_type_arg)
95 const std::type_info &source_type() const
99 const std::type_info &target_type() const
104 virtual const char *what() const throw()
106 return "bad lexical cast: "
107 "source type value could not be interpreted as target";
109 virtual ~bad_lexical_cast() throw()
113 const std::type_info *source;
114 const std::type_info *target;
117 namespace detail // selectors for choosing stream character type
119 template<typename Type>
125 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
126 template<class CharT, class Traits, class Alloc>
127 struct stream_char< std::basic_string<CharT,Traits,Alloc> >
133 #ifndef BOOST_LCAST_NO_WCHAR_T
134 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
136 struct stream_char<wchar_t>
138 typedef wchar_t type;
143 struct stream_char<wchar_t *>
145 typedef wchar_t type;
149 struct stream_char<const wchar_t *>
151 typedef wchar_t type;
154 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
156 struct stream_char<std::wstring>
158 typedef wchar_t type;
163 template<typename TargetChar, typename SourceChar>
166 typedef TargetChar type;
170 struct widest_char<char, wchar_t>
172 typedef wchar_t type;
176 namespace detail // deduce_char_traits template
178 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
179 template<class CharT, class Target, class Source>
180 struct deduce_char_traits
182 typedef std::char_traits<CharT> type;
185 template<class CharT, class Traits, class Alloc, class Source>
186 struct deduce_char_traits< CharT
187 , std::basic_string<CharT,Traits,Alloc>
194 template<class CharT, class Target, class Traits, class Alloc>
195 struct deduce_char_traits< CharT
197 , std::basic_string<CharT,Traits,Alloc>
203 template<class CharT, class Traits, class Alloc1, class Alloc2>
204 struct deduce_char_traits< CharT
205 , std::basic_string<CharT,Traits,Alloc1>
206 , std::basic_string<CharT,Traits,Alloc2>
214 namespace detail // lcast_src_length
216 // Return max. length of string representation of Source;
217 // 0 if unlimited (with exceptions for some types, see below).
218 // Values with limited string representation are placed to
219 // the buffer locally defined in lexical_cast function.
220 // 1 is returned for few types such as CharT const* or
221 // std::basic_string<CharT> that already have an internal
222 // buffer ready to be reused by lexical_stream_limited_src.
223 // Each specialization should have a correspondent operator<<
224 // defined in lexical_stream_limited_src.
225 template< class CharT // A result of widest_char transformation.
226 , class Source // Source type of lexical_cast.
228 struct lcast_src_length
230 BOOST_STATIC_CONSTANT(std::size_t, value = 0);
231 // To check coverage, build the test with
232 // bjam --v2 profile optimization=off
233 static void check_coverage() {}
237 struct lcast_src_length<char, bool>
239 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
240 static void check_coverage() {}
244 struct lcast_src_length<char, char>
246 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
247 static void check_coverage() {}
251 struct lcast_src_length<char, signed char>
253 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
254 static void check_coverage() {}
257 struct lcast_src_length<char, unsigned char>
259 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
260 static void check_coverage() {}
263 struct lcast_src_length<char, signed char*>
265 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
266 static void check_coverage() {}
269 struct lcast_src_length<char, unsigned char*>
271 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
272 static void check_coverage() {}
275 struct lcast_src_length<char, signed char const*>
277 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
278 static void check_coverage() {}
281 struct lcast_src_length<char, unsigned char const*>
283 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
284 static void check_coverage() {}
287 #ifndef BOOST_LCAST_NO_WCHAR_T
289 struct lcast_src_length<wchar_t, bool>
291 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
292 static void check_coverage() {}
296 struct lcast_src_length<wchar_t, char>
298 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
299 static void check_coverage() {}
302 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
304 struct lcast_src_length<wchar_t, wchar_t>
306 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
307 static void check_coverage() {}
313 struct lcast_src_length<char, char const*>
315 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
316 static void check_coverage() {}
320 struct lcast_src_length<char, char*>
322 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
323 static void check_coverage() {}
326 #ifndef BOOST_LCAST_NO_WCHAR_T
328 struct lcast_src_length<wchar_t, wchar_t const*>
330 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
331 static void check_coverage() {}
335 struct lcast_src_length<wchar_t, wchar_t*>
337 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
338 static void check_coverage() {}
342 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
343 template<class CharT, class Traits, class Alloc>
344 struct lcast_src_length< CharT, std::basic_string<CharT,Traits,Alloc> >
346 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
347 static void check_coverage() {}
351 struct lcast_src_length< char, std::basic_string<char> >
353 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
354 static void check_coverage() {}
357 #ifndef BOOST_LCAST_NO_WCHAR_T
359 struct lcast_src_length< wchar_t, std::basic_string<wchar_t> >
361 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
362 static void check_coverage() {}
367 // Helper for integral types.
368 // Notes on length calculation:
369 // Max length for 32bit int with grouping "\1" and thousands_sep ',':
370 // "-2,1,4,7,4,8,3,6,4,7"
372 // ^ - 1 digit not counted by digits10
373 // ^^^^^^^^^^^^^^^^^^ - digits10 * 2
375 // Constant is_specialized is used instead of constant 1
376 // to prevent buffer overflow in a rare case when
377 // <boost/limits.hpp> doesn't add missing specialization for
378 // numeric_limits<T> for some integral type T.
379 // When is_specialized is false, the whole expression is 0.
380 template<class Source>
381 struct lcast_src_length_integral
383 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
384 BOOST_STATIC_CONSTANT(std::size_t, value =
385 std::numeric_limits<Source>::is_signed +
386 std::numeric_limits<Source>::is_specialized + // == 1
387 std::numeric_limits<Source>::digits10 * 2
390 BOOST_STATIC_CONSTANT(std::size_t, value = 156);
391 BOOST_STATIC_ASSERT(sizeof(Source) * CHAR_BIT <= 256);
395 #define BOOST_LCAST_DEF1(CharT, T) \
396 template<> struct lcast_src_length<CharT, T> \
397 : lcast_src_length_integral<T> \
398 { static void check_coverage() {} };
400 #ifdef BOOST_LCAST_NO_WCHAR_T
401 #define BOOST_LCAST_DEF(T) BOOST_LCAST_DEF1(char, T)
403 #define BOOST_LCAST_DEF(T) \
404 BOOST_LCAST_DEF1(char, T) \
405 BOOST_LCAST_DEF1(wchar_t, T)
408 BOOST_LCAST_DEF(short)
409 BOOST_LCAST_DEF(unsigned short)
411 BOOST_LCAST_DEF(unsigned int)
412 BOOST_LCAST_DEF(long)
413 BOOST_LCAST_DEF(unsigned long)
414 #if defined(BOOST_HAS_LONG_LONG)
415 BOOST_LCAST_DEF(boost::ulong_long_type)
416 BOOST_LCAST_DEF(boost::long_long_type )
417 #elif defined(BOOST_HAS_MS_INT64)
418 BOOST_LCAST_DEF(unsigned __int64)
419 BOOST_LCAST_DEF( __int64)
422 #undef BOOST_LCAST_DEF
423 #undef BOOST_LCAST_DEF1
425 #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
426 // Helper for floating point types.
427 // -1.23456789e-123456
431 // ^^^^^^^^ lcast_precision<Source>::value
434 // ^^^^^^ exponent (assumed 6 or less digits)
435 // sign + leading digit + decimal point + "e" + exponent sign == 5
436 template<class Source>
437 struct lcast_src_length_floating
440 std::numeric_limits<Source>::max_exponent10 <= 999999L &&
441 std::numeric_limits<Source>::min_exponent10 >= -999999L
443 BOOST_STATIC_CONSTANT(std::size_t, value =
444 5 + lcast_precision<Source>::value + 6
449 struct lcast_src_length<char,float>
450 : lcast_src_length_floating<float>
452 static void check_coverage() {}
456 struct lcast_src_length<char,double>
457 : lcast_src_length_floating<double>
459 static void check_coverage() {}
463 struct lcast_src_length<char,long double>
464 : lcast_src_length_floating<long double>
466 static void check_coverage() {}
469 #ifndef BOOST_LCAST_NO_WCHAR_T
471 struct lcast_src_length<wchar_t,float>
472 : lcast_src_length_floating<float>
474 static void check_coverage() {}
478 struct lcast_src_length<wchar_t,double>
479 : lcast_src_length_floating<double>
481 static void check_coverage() {}
485 struct lcast_src_length<wchar_t,long double>
486 : lcast_src_length_floating<long double>
488 static void check_coverage() {}
491 #endif // #ifndef BOOST_LCAST_NO_WCHAR_T
492 #endif // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
495 namespace detail // '0', '+' and '-' constants
497 template<typename CharT> struct lcast_char_constants;
500 struct lcast_char_constants<char>
502 BOOST_STATIC_CONSTANT(char, zero = '0');
503 BOOST_STATIC_CONSTANT(char, minus = '-');
504 BOOST_STATIC_CONSTANT(char, plus = '+');
507 #ifndef BOOST_LCAST_NO_WCHAR_T
509 struct lcast_char_constants<wchar_t>
511 BOOST_STATIC_CONSTANT(wchar_t, zero = L'0');
512 BOOST_STATIC_CONSTANT(wchar_t, minus = L'-');
513 BOOST_STATIC_CONSTANT(wchar_t, plus = L'+');
518 namespace detail // lexical_streambuf_fake
520 struct lexical_streambuf_fake
525 namespace detail // lcast_to_unsigned
527 #if (defined _MSC_VER)
528 # pragma warning( push )
529 // C4146: unary minus operator applied to unsigned type, result still unsigned
530 # pragma warning( disable : 4146 )
531 #elif defined( __BORLANDC__ )
532 # pragma option push -w-8041
536 BOOST_DEDUCED_TYPENAME make_unsigned<T>::type lcast_to_unsigned(T value)
538 typedef BOOST_DEDUCED_TYPENAME make_unsigned<T>::type result_type;
539 result_type uvalue = static_cast<result_type>(value);
540 return value < 0 ? -uvalue : uvalue;
542 #if (defined _MSC_VER)
543 # pragma warning( pop )
544 #elif defined( __BORLANDC__ )
549 namespace detail // lcast_put_unsigned
551 template<class Traits, class T, class CharT>
552 CharT* lcast_put_unsigned(T n, CharT* finish)
554 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
555 BOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_signed);
558 typedef typename Traits::int_type int_type;
559 CharT const czero = lcast_char_constants<CharT>::zero;
560 int_type const zero = Traits::to_int_type(czero);
562 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
563 // TODO: use BOOST_NO_STD_LOCALE
565 typedef std::numpunct<CharT> numpunct;
566 numpunct const& np = BOOST_USE_FACET(numpunct, loc);
567 std::string const& grouping = np.grouping();
568 std::string::size_type const grouping_size = grouping.size();
570 if ( grouping_size && grouping[0] > 0 )
573 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
574 // Check that ulimited group is unreachable:
575 BOOST_STATIC_ASSERT(std::numeric_limits<T>::digits10 < CHAR_MAX);
577 CharT thousands_sep = np.thousands_sep();
578 std::string::size_type group = 0; // current group number
579 char last_grp_size = grouping[0];
580 char left = last_grp_size;
587 if(group < grouping_size)
589 char const grp_size = grouping[group];
590 last_grp_size = grp_size <= 0 ? CHAR_MAX : grp_size;
593 left = last_grp_size;
595 Traits::assign(*finish, thousands_sep);
601 int_type const digit = static_cast<int_type>(n % 10U);
602 Traits::assign(*finish, Traits::to_char_type(zero + digit));
612 int_type const digit = static_cast<int_type>(n % 10U);
613 Traits::assign(*finish, Traits::to_char_type(zero + digit));
622 namespace detail // lcast_ret_unsigned
624 template<class Traits, class T, class CharT>
625 inline bool lcast_ret_unsigned(T& value, const CharT* const begin, const CharT* end)
627 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
628 BOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_signed);
630 typedef typename Traits::int_type int_type;
631 CharT const czero = lcast_char_constants<CharT>::zero;
635 if ( *end < czero || *end >= czero + 10 || begin > end)
637 value = *end - czero;
641 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
642 // TODO: use BOOST_NO_STD_LOCALE
644 typedef std::numpunct<CharT> numpunct;
645 numpunct const& np = BOOST_USE_FACET(numpunct, loc);
646 std::string const& grouping = np.grouping();
647 std::string::size_type const grouping_size = grouping.size();
649 /* According to [22.2.2.1.2] of Programming languages - C++
650 * we MUST check for correct grouping
652 if (grouping_size && grouping[0] > 0)
654 unsigned char current_grouping = 0;
655 CharT const thousands_sep = np.thousands_sep();
656 char remained = grouping[current_grouping] - 1;
657 bool shall_we_return = true;
659 for(;end>=begin; --end)
662 T const new_sub_value = multiplier * 10 * (*end - czero);
664 if (*end < czero || *end >= czero + 10
665 /* detecting overflow */
666 || new_sub_value/10 != multiplier * (*end - czero)
667 || static_cast<T>((std::numeric_limits<T>::max)()-new_sub_value) < value
671 value += new_sub_value;
675 if ( !Traits::eq(*end, thousands_sep) ) //|| begin == end ) return false;
678 * According to Programming languages - C++
679 * Digit grouping is checked. That is, the positions of discarded
680 * separators is examined for consistency with
681 * use_facet<numpunct<charT> >(loc ).grouping()
683 * BUT what if there is no separators at all and grouping()
684 * is not empty? Well, we have no extraced separators, so we
685 * won`t check them for consistency. This will allow us to
686 * work with "C" locale from other locales
688 shall_we_return = false;
691 if ( begin == end ) return false;
692 if (current_grouping < grouping_size-1 ) ++current_grouping;
693 remained = grouping[current_grouping];
698 if (shall_we_return) return true;
702 while ( begin <= end )
704 T const new_sub_value = multiplier * 10 * (*end - czero);
706 if (*end < czero || *end >= czero + 10
707 /* detecting overflow */
708 || new_sub_value/10 != multiplier * (*end - czero)
709 || static_cast<T>((std::numeric_limits<T>::max)()-new_sub_value) < value
713 value += new_sub_value;
722 namespace detail // stream wrapper for handling lexical conversions
724 template<typename Target, typename Source, typename Traits>
728 typedef typename widest_char<
729 typename stream_char<Target>::type,
730 typename stream_char<Source>::type>::type char_type;
732 typedef Traits traits_type;
735 lexical_stream(char_type* = 0, char_type* = 0)
737 stream.unsetf(std::ios::skipws);
738 lcast_set_precision(stream, static_cast<Source*>(0), static_cast<Target*>(0) );
742 #if defined(BOOST_NO_STRINGSTREAM)
743 stream.freeze(false);
746 bool operator<<(const Source &input)
748 return !(stream << input).fail();
750 template<typename InputStreamable>
751 bool operator>>(InputStreamable &output)
753 return !is_pointer<InputStreamable>::value &&
756 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
757 // GCC 2.9x lacks std::char_traits<>::eof().
758 // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
759 // configurations, which do provide std::char_traits<>::eof().
767 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
769 bool operator>>(std::string &output)
771 #if defined(BOOST_NO_STRINGSTREAM)
774 stream.str().swap(output);
777 #ifndef BOOST_LCAST_NO_WCHAR_T
778 bool operator>>(std::wstring &output)
780 stream.str().swap(output);
786 bool operator>>(std::basic_string<char_type,traits_type>& output)
788 stream.str().swap(output);
792 template<class Alloc>
793 bool operator>>(std::basic_string<char_type,traits_type,Alloc>& out)
795 std::basic_string<char_type,traits_type> str(stream.str());
796 out.assign(str.begin(), str.end());
801 #if defined(BOOST_NO_STRINGSTREAM)
802 std::strstream stream;
803 #elif defined(BOOST_NO_STD_LOCALE)
804 std::stringstream stream;
806 std::basic_stringstream<char_type,traits_type> stream;
811 namespace detail // optimized stream wrapper
813 // String representation of Source has an upper limit.
814 template< class CharT // a result of widest_char transformation
815 , class Base // lexical_streambuf_fake or basic_streambuf<CharT>
816 , class Traits // usually char_traits<CharT>
818 class lexical_stream_limited_src : public Base
820 // A string representation of Source is written to [start, finish).
821 // Currently, it is assumed that [start, finish) is big enough
822 // to hold a string representation of any Source value.
828 static void widen_and_assign(char*p, char ch)
830 Traits::assign(*p, ch);
833 #ifndef BOOST_LCAST_NO_WCHAR_T
834 static void widen_and_assign(wchar_t* p, char ch)
836 // TODO: use BOOST_NO_STD_LOCALE
838 wchar_t w = BOOST_USE_FACET(std::ctype<wchar_t>, loc).widen(ch);
839 Traits::assign(*p, w);
842 static void widen_and_assign(wchar_t* p, wchar_t ch)
844 Traits::assign(*p, ch);
847 static void widen_and_assign(char*, wchar_t ch); // undefined
850 template<class OutputStreamable>
851 bool lcast_put(const OutputStreamable& input)
853 this->setp(start, finish);
854 std::basic_ostream<CharT> stream(static_cast<Base*>(this));
855 lcast_set_precision(stream, static_cast<OutputStreamable*>(0));
856 bool const result = !(stream << input).fail();
857 finish = this->pptr();
862 lexical_stream_limited_src(lexical_stream_limited_src const&);
863 void operator=(lexical_stream_limited_src const&);
867 lexical_stream_limited_src(CharT* sta, CharT* fin)
874 template<class Alloc>
875 bool operator<<(std::basic_string<CharT,Traits,Alloc> const& str)
877 start = const_cast<CharT*>(str.data());
878 finish = start + str.length();
882 bool operator<<(bool);
883 bool operator<<(char);
884 bool operator<<(unsigned char);
885 bool operator<<(signed char);
886 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
887 bool operator<<(wchar_t);
889 bool operator<<(unsigned char const*);
890 bool operator<<(signed char const*);
891 bool operator<<(CharT const*);
892 bool operator<<(short);
893 bool operator<<(int);
894 bool operator<<(long);
895 bool operator<<(unsigned short);
896 bool operator<<(unsigned int);
897 bool operator<<(unsigned long);
898 #if defined(BOOST_HAS_LONG_LONG)
899 bool operator<<(boost::ulong_long_type);
900 bool operator<<(boost::long_long_type );
901 #elif defined(BOOST_HAS_MS_INT64)
902 bool operator<<(unsigned __int64);
903 bool operator<<( __int64);
905 // These three operators use ostream and streambuf.
906 // lcast_streambuf_for_source<T>::value is true.
907 bool operator<<(float);
908 bool operator<<(double);
909 bool operator<<(long double);
913 template <typename Type>
914 bool input_operator_helper_unsigned(Type& output)
916 CharT const minus = lcast_char_constants<CharT>::minus;
917 CharT const plus = lcast_char_constants<CharT>::plus;
918 bool has_minus = false;
920 /* We won`t use `start' any more, so no need in decrementing it after */
921 if ( Traits::eq(minus,*start) )
925 } else if ( Traits::eq( plus, *start ) )
930 bool const succeed = lcast_ret_unsigned<Traits>(output, start, finish);
931 #if (defined _MSC_VER)
932 # pragma warning( push )
933 // C4146: unary minus operator applied to unsigned type, result still unsigned
934 # pragma warning( disable : 4146 )
935 #elif defined( __BORLANDC__ )
936 # pragma option push -w-8041
938 if (has_minus) output = static_cast<Type>(-output);
939 #if (defined _MSC_VER)
940 # pragma warning( pop )
941 #elif defined( __BORLANDC__ )
947 template <typename Type>
948 bool input_operator_helper_signed(Type& output)
950 CharT const minus = lcast_char_constants<CharT>::minus;
951 CharT const plus = lcast_char_constants<CharT>::plus;
952 typedef BOOST_DEDUCED_TYPENAME make_unsigned<Type>::type utype;
954 bool has_minus = false;
956 /* We won`t use `start' any more, so no need in decrementing it after */
957 if ( Traits::eq(minus,*start) )
961 } else if ( Traits::eq(plus, *start) )
966 bool succeed = lcast_ret_unsigned<Traits>(out_tmp, start, finish);
968 #if (defined _MSC_VER)
969 # pragma warning( push )
970 // C4146: unary minus operator applied to unsigned type, result still unsigned
971 # pragma warning( disable : 4146 )
972 #elif defined( __BORLANDC__ )
973 # pragma option push -w-8041
975 utype const comp_val = static_cast<utype>(-(std::numeric_limits<Type>::min)());
976 succeed = succeed && out_tmp<=comp_val;
978 #if (defined _MSC_VER)
979 # pragma warning( pop )
980 #elif defined( __BORLANDC__ )
984 utype const comp_val = static_cast<utype>((std::numeric_limits<Type>::max)());
985 succeed = succeed && out_tmp<=comp_val;
993 bool operator>>(unsigned short& output)
995 return input_operator_helper_unsigned(output);
998 bool operator>>(unsigned int& output)
1000 return input_operator_helper_unsigned(output);
1003 bool operator>>(unsigned long int& output)
1005 return input_operator_helper_unsigned(output);
1008 bool operator>>(short& output)
1010 return input_operator_helper_signed(output);
1013 bool operator>>(int& output)
1015 return input_operator_helper_signed(output);
1018 bool operator>>(long int& output)
1020 return input_operator_helper_signed(output);
1024 #if defined(BOOST_HAS_LONG_LONG)
1025 bool operator>>( boost::ulong_long_type& output)
1027 return input_operator_helper_unsigned(output);
1030 bool operator>>(boost::long_long_type& output)
1032 return input_operator_helper_signed(output);
1035 #elif defined(BOOST_HAS_MS_INT64)
1036 bool operator>>(unsigned __int64& output)
1038 return input_operator_helper_unsigned(output);
1041 bool operator>>(__int64& output)
1043 return input_operator_helper_signed(output);
1049 * case "-0" || "0" || "+0" : output = false; return true;
1050 * case "1" || "+1": output = true; return true;
1051 * default: return false;
1053 bool operator>>(bool& output)
1055 CharT const zero = lcast_char_constants<CharT>::zero;
1056 CharT const plus = lcast_char_constants<CharT>::plus;
1057 CharT const minus = lcast_char_constants<CharT>::minus;
1059 switch(finish-start)
1062 output = Traits::eq(start[0], zero+1);
1063 return output || Traits::eq(start[0], zero );
1065 if ( Traits::eq( plus, *start) )
1068 output = Traits::eq(start[0], zero +1);
1069 return output || Traits::eq(start[0], zero );
1073 return Traits::eq( minus, *start)
1074 && Traits::eq( zero, start[1]);
1077 output = false; // Suppress warning about uninitalized variable
1083 // Generic istream-based algorithm.
1084 // lcast_streambuf_for_target<InputStreamable>::value is true.
1085 template<typename InputStreamable>
1086 bool operator>>(InputStreamable& output)
1088 #if (defined _MSC_VER)
1089 # pragma warning( push )
1090 // conditional expression is constant
1091 # pragma warning( disable : 4127 )
1093 if(is_pointer<InputStreamable>::value)
1096 this->setg(start, start, finish);
1097 std::basic_istream<CharT> stream(static_cast<Base*>(this));
1098 stream.unsetf(std::ios::skipws);
1099 lcast_set_precision(stream, static_cast<InputStreamable*>(0));
1100 #if (defined _MSC_VER)
1101 # pragma warning( pop )
1103 return stream >> output &&
1105 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
1106 // GCC 2.9x lacks std::char_traits<>::eof().
1107 // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
1108 // configurations, which do provide std::char_traits<>::eof().
1116 bool operator>>(CharT&);
1117 bool operator>>(unsigned char&);
1118 bool operator>>(signed char&);
1120 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1121 // This #if is in sync with lcast_streambuf_for_target
1123 bool operator>>(std::string&);
1125 #ifndef BOOST_LCAST_NO_WCHAR_T
1126 bool operator>>(std::wstring&);
1130 template<class Alloc>
1131 bool operator>>(std::basic_string<CharT,Traits,Alloc>& str)
1133 str.assign(start, finish);
1139 template<typename CharT, class Base, class Traits>
1140 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1143 typedef typename Traits::int_type int_type;
1144 CharT const czero = lcast_char_constants<CharT>::zero;
1145 int_type const zero = Traits::to_int_type(czero);
1146 Traits::assign(*start, Traits::to_char_type(zero + value));
1151 template<typename CharT, class Base, class Traits>
1152 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1155 widen_and_assign(start, ch);
1160 template<typename CharT, class Base, class Traits>
1161 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1164 return ((*this) << static_cast<char>(ch));
1167 template<typename CharT, class Base, class Traits>
1168 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1171 return ((*this) << static_cast<char>(ch));
1174 template<typename CharT, class Base, class Traits>
1175 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1176 unsigned char const* ch)
1178 return ((*this) << reinterpret_cast<char const*>(ch));
1181 template<typename CharT, class Base, class Traits>
1182 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1183 signed char const* ch)
1185 return ((*this) << reinterpret_cast<char const*>(ch));
1188 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
1189 template<typename CharT, class Base, class Traits>
1190 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1193 widen_and_assign(start, ch);
1199 template<typename CharT, class Base, class Traits>
1200 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1203 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
1207 CharT const minus = lcast_char_constants<CharT>::minus;
1208 Traits::assign(*start, minus);
1213 template<typename CharT, class Base, class Traits>
1214 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1217 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
1221 CharT const minus = lcast_char_constants<CharT>::minus;
1222 Traits::assign(*start, minus);
1227 template<typename CharT, class Base, class Traits>
1228 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1231 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
1235 CharT const minus = lcast_char_constants<CharT>::minus;
1236 Traits::assign(*start, minus);
1241 #if defined(BOOST_HAS_LONG_LONG)
1242 template<typename CharT, class Base, class Traits>
1243 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1244 boost::long_long_type n)
1246 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
1250 CharT const minus = lcast_char_constants<CharT>::minus;
1251 Traits::assign(*start, minus);
1255 #elif defined(BOOST_HAS_MS_INT64)
1256 template<typename CharT, class Base, class Traits>
1257 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1260 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
1264 CharT const minus = lcast_char_constants<CharT>::minus;
1265 Traits::assign(*start, minus);
1271 template<typename CharT, class Base, class Traits>
1272 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1275 start = lcast_put_unsigned<Traits>(n, finish);
1279 template<typename CharT, class Base, class Traits>
1280 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1283 start = lcast_put_unsigned<Traits>(n, finish);
1287 template<typename CharT, class Base, class Traits>
1288 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1291 start = lcast_put_unsigned<Traits>(n, finish);
1295 #if defined(BOOST_HAS_LONG_LONG)
1296 template<typename CharT, class Base, class Traits>
1297 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1298 boost::ulong_long_type n)
1300 start = lcast_put_unsigned<Traits>(n, finish);
1303 #elif defined(BOOST_HAS_MS_INT64)
1304 template<typename CharT, class Base, class Traits>
1305 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1308 start = lcast_put_unsigned<Traits>(n, finish);
1313 template<typename CharT, class Base, class Traits>
1314 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1317 return this->lcast_put(val);
1320 template<typename CharT, class Base, class Traits>
1321 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1324 return this->lcast_put(val);
1327 template<typename CharT, class Base, class Traits>
1328 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1331 return this->lcast_put(val);
1334 template<typename CharT, class Base, class Traits>
1335 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1338 start = const_cast<CharT*>(str);
1339 finish = start + Traits::length(str);
1343 template<typename CharT, class Base, class Traits>
1344 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
1347 bool const ok = (finish - start == 1);
1349 Traits::assign(output, *start);
1353 template<typename CharT, class Base, class Traits>
1354 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
1355 unsigned char& output)
1357 BOOST_STATIC_ASSERT( sizeof(CharT) == sizeof(unsigned char) );
1358 bool const ok = (finish - start == 1);
1361 Traits::assign(out, *start);
1362 output = static_cast<signed char>(out);
1367 template<typename CharT, class Base, class Traits>
1368 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
1369 signed char& output)
1371 BOOST_STATIC_ASSERT( sizeof(CharT) == sizeof(signed char) );
1372 bool const ok = (finish - start == 1);
1375 Traits::assign(out, *start);
1376 output = static_cast<signed char>(out);
1381 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1382 template<typename CharT, class Base, class Traits>
1383 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
1386 str.assign(start, finish);
1390 #ifndef BOOST_LCAST_NO_WCHAR_T
1391 template<typename CharT, class Base, class Traits>
1392 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
1395 str.assign(start, finish);
1402 namespace detail // lcast_streambuf_for_source
1404 // Returns true if optimized stream wrapper needs ostream for writing.
1405 template<class Source>
1406 struct lcast_streambuf_for_source
1408 BOOST_STATIC_CONSTANT(bool, value = false);
1412 struct lcast_streambuf_for_source<float>
1414 BOOST_STATIC_CONSTANT(bool, value = true);
1418 struct lcast_streambuf_for_source<double>
1420 BOOST_STATIC_CONSTANT(bool, value = true);
1424 struct lcast_streambuf_for_source<long double>
1426 BOOST_STATIC_CONSTANT(bool, value = true);
1430 namespace detail // lcast_streambuf_for_target
1432 // Returns true if optimized stream wrapper needs istream for reading.
1433 template<class Target>
1434 struct lcast_streambuf_for_target
1436 BOOST_STATIC_CONSTANT(bool, value =
1438 ::boost::type_traits::ice_not< is_integral<Target>::value >::value
1443 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1444 template<class Traits, class Alloc>
1445 struct lcast_streambuf_for_target<
1446 std::basic_string<char,Traits,Alloc> >
1448 BOOST_STATIC_CONSTANT(bool, value = false);
1451 #ifndef BOOST_LCAST_NO_WCHAR_T
1452 template<class Traits, class Alloc>
1453 struct lcast_streambuf_for_target<
1454 std::basic_string<wchar_t,Traits,Alloc> >
1456 BOOST_STATIC_CONSTANT(bool, value = false);
1461 struct lcast_streambuf_for_target<std::string>
1463 BOOST_STATIC_CONSTANT(bool, value = false);
1466 #ifndef BOOST_LCAST_NO_WCHAR_T
1468 struct lcast_streambuf_for_target<std::wstring>
1470 BOOST_STATIC_CONSTANT(bool, value = false);
1476 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1478 // call-by-const reference version
1483 struct array_to_pointer_decay
1488 template<class T, std::size_t N>
1489 struct array_to_pointer_decay<T[N]>
1491 typedef const T * type;
1494 #if (defined _MSC_VER)
1495 # pragma warning( push )
1496 # pragma warning( disable : 4701 ) // possible use of ... before initialization
1497 # pragma warning( disable : 4702 ) // unreachable code
1498 # pragma warning( disable : 4267 ) // conversion from 'size_t' to 'unsigned int'
1501 template< typename Target
1503 , bool Unlimited // string representation of Source is unlimited
1506 Target lexical_cast(
1507 BOOST_DEDUCED_TYPENAME boost::call_traits<Source>::param_type arg,
1508 CharT* buf, std::size_t src_len)
1510 typedef BOOST_DEDUCED_TYPENAME
1511 deduce_char_traits<CharT,Target,Source>::type traits;
1513 typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
1514 lcast_streambuf_for_target<Target>::value ||
1515 lcast_streambuf_for_source<Source>::value
1516 , std::basic_streambuf<CharT>
1517 , lexical_streambuf_fake
1520 BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
1522 , detail::lexical_stream<Target,Source,traits>
1523 , detail::lexical_stream_limited_src<CharT,base,traits>
1524 >::type interpreter(buf, buf + src_len);
1527 if(!(interpreter << arg && interpreter >> result))
1528 BOOST_LCAST_THROW_BAD_CAST(Source, Target);
1531 #if (defined _MSC_VER)
1532 # pragma warning( pop )
1535 template<typename T>
1538 BOOST_STATIC_CONSTANT(bool, value = false );
1541 template<typename CharT, typename Traits, typename Alloc>
1542 struct is_stdstring< std::basic_string<CharT, Traits, Alloc> >
1544 BOOST_STATIC_CONSTANT(bool, value = true );
1547 template<typename T>
1548 struct is_char_or_wchar
1550 #ifndef BOOST_LCAST_NO_WCHAR_T
1551 BOOST_STATIC_CONSTANT(bool, value =
1553 ::boost::type_traits::ice_or<
1554 is_same< T, char >::value,
1555 is_same< T, wchar_t >::value,
1556 is_same< T, unsigned char >::value,
1557 is_same< T, signed char >::value
1562 BOOST_STATIC_CONSTANT(bool, value =
1564 ::boost::type_traits::ice_or<
1565 is_same< T, char >::value,
1566 is_same< T, unsigned char >::value,
1567 is_same< T, signed char >::value
1574 template<typename Target, typename Source>
1575 struct is_arithmetic_and_not_xchars
1577 BOOST_STATIC_CONSTANT(bool, value =
1579 ::boost::type_traits::ice_and<
1580 is_arithmetic<Source>::value,
1581 is_arithmetic<Target>::value,
1582 ::boost::type_traits::ice_not<
1583 detail::is_char_or_wchar<Target>::value
1585 ::boost::type_traits::ice_not<
1586 detail::is_char_or_wchar<Source>::value
1594 * is_xchar_to_xchar<Target, Source>::value is true, when
1595 * Target and Souce are the same char types, or when
1596 * Target and Souce are char types of the same size.
1598 template<typename Target, typename Source>
1599 struct is_xchar_to_xchar
1601 BOOST_STATIC_CONSTANT(bool, value =
1603 ::boost::type_traits::ice_or<
1604 ::boost::type_traits::ice_and<
1605 is_same<Source,Target>::value,
1606 is_char_or_wchar<Target>::value
1608 ::boost::type_traits::ice_and<
1609 ::boost::type_traits::ice_eq< sizeof(char),sizeof(Target)>::value,
1610 ::boost::type_traits::ice_eq< sizeof(char),sizeof(Source)>::value,
1611 is_char_or_wchar<Target>::value,
1612 is_char_or_wchar<Source>::value
1619 template<typename Target, typename Source>
1620 struct is_char_array_to_stdstring
1622 BOOST_STATIC_CONSTANT(bool, value = false );
1625 template<typename CharT, typename Traits, typename Alloc>
1626 struct is_char_array_to_stdstring< std::basic_string<CharT, Traits, Alloc>, CharT* >
1628 BOOST_STATIC_CONSTANT(bool, value = true );
1631 template<typename CharT, typename Traits, typename Alloc>
1632 struct is_char_array_to_stdstring< std::basic_string<CharT, Traits, Alloc>, const CharT* >
1634 BOOST_STATIC_CONSTANT(bool, value = true );
1637 template<typename Target, typename Source>
1638 struct lexical_cast_do_cast
1640 static inline Target lexical_cast_impl(const Source &arg)
1642 typedef typename detail::array_to_pointer_decay<Source>::type src;
1644 typedef typename detail::widest_char<
1645 typename detail::stream_char<Target>::type
1646 , typename detail::stream_char<src>::type
1649 typedef detail::lcast_src_length<char_type, src> lcast_src_length;
1650 std::size_t const src_len = lcast_src_length::value;
1651 char_type buf[src_len + 1];
1652 lcast_src_length::check_coverage();
1653 return detail::lexical_cast<Target, src, !src_len>(arg, buf, src_len);
1657 template<typename Source>
1658 struct lexical_cast_copy
1660 static inline Source lexical_cast_impl(const Source &arg)
1666 class precision_loss_error : public boost::numeric::bad_numeric_cast
1669 virtual const char * what() const throw()
1670 { return "bad numeric conversion: precision loss error"; }
1674 struct throw_on_precision_loss
1676 typedef boost::numeric::Trunc<S> Rounder;
1677 typedef S source_type ;
1679 typedef typename mpl::if_< is_arithmetic<S>,S,S const&>::type argument_type ;
1681 static source_type nearbyint ( argument_type s )
1683 source_type orig_div_round = s / Rounder::nearbyint(s);
1685 if ( (orig_div_round > 1 ? orig_div_round - 1 : 1 - orig_div_round) > std::numeric_limits<source_type>::epsilon() )
1686 BOOST_THROW_EXCEPTION( precision_loss_error() );
1690 typedef typename Rounder::round_style round_style;
1693 template<typename Target, typename Source>
1694 struct lexical_cast_dynamic_num_not_ignoring_minus
1696 static inline Target lexical_cast_impl(const Source &arg)
1699 typedef boost::numeric::converter<
1702 boost::numeric::conversion_traits<Target,Source>,
1703 boost::numeric::def_overflow_handler,
1704 throw_on_precision_loss<Source>
1707 return Converter::convert(arg);
1708 } catch( ::boost::numeric::bad_numeric_cast const& ) {
1709 BOOST_LCAST_THROW_BAD_CAST(Source, Target);
1714 template<typename Target, typename Source>
1715 struct lexical_cast_dynamic_num_ignoring_minus
1717 static inline Target lexical_cast_impl(const Source &arg)
1720 typedef boost::numeric::converter<
1723 boost::numeric::conversion_traits<Target,Source>,
1724 boost::numeric::def_overflow_handler,
1725 throw_on_precision_loss<Source>
1728 bool has_minus = ( arg < 0);
1730 return static_cast<Target>(-Converter::convert(-arg));
1732 return Converter::convert(arg);
1734 } catch( ::boost::numeric::bad_numeric_cast const& ) {
1735 BOOST_LCAST_THROW_BAD_CAST(Source, Target);
1741 * lexical_cast_dynamic_num follows the rules:
1742 * 1) If Source can be converted to Target without precision loss and
1743 * without overflows, then assign Source to Target and return
1745 * 2) If Source is less than 0 and Target is an unsigned integer,
1746 * then negate Source, check the requirements of rule 1) and if
1747 * successful, assign static_casted Source to Target and return
1749 * 3) Otherwise throw a bad_lexical_cast exception
1752 * Rule 2) required because boost::lexical_cast has the behavior of
1753 * stringstream, which uses the rules of scanf for conversions. And
1754 * in the C99 standard for unsigned input value minus sign is
1755 * optional, so if a negative number is read, no errors will arise
1756 * and the result will be the two's complement.
1758 template<typename Target, typename Source>
1759 struct lexical_cast_dynamic_num
1761 static inline Target lexical_cast_impl(const Source &arg)
1763 typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
1764 ::boost::type_traits::ice_and<
1765 ::boost::type_traits::ice_or<
1766 ::boost::is_signed<Source>::value,
1767 ::boost::is_float<Source>::value
1769 ::boost::type_traits::ice_not<
1770 is_same<Source, bool>::value
1772 ::boost::type_traits::ice_not<
1773 is_same<Target, bool>::value
1775 ::boost::is_unsigned<Target>::value
1777 lexical_cast_dynamic_num_ignoring_minus<Target, Source>,
1778 lexical_cast_dynamic_num_not_ignoring_minus<Target, Source>
1779 >::type caster_type;
1781 return caster_type::lexical_cast_impl(arg);
1786 template<typename Target, typename Source>
1787 inline Target lexical_cast(const Source &arg)
1789 typedef BOOST_DEDUCED_TYPENAME detail::array_to_pointer_decay<Source>::type src;
1791 typedef BOOST_DEDUCED_TYPENAME ::boost::type_traits::ice_or<
1792 detail::is_xchar_to_xchar<Target, src>::value,
1793 detail::is_char_array_to_stdstring<Target,src>::value,
1794 ::boost::type_traits::ice_and<
1795 is_same<Target, src>::value,
1796 detail::is_stdstring<Target>::value
1800 typedef BOOST_DEDUCED_TYPENAME
1801 detail::is_arithmetic_and_not_xchars<Target, src> do_copy_with_dynamic_check_type;
1803 typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
1804 do_copy_type::value,
1805 detail::lexical_cast_copy<src>,
1806 BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
1807 do_copy_with_dynamic_check_type::value,
1808 detail::lexical_cast_dynamic_num<Target, src>,
1809 detail::lexical_cast_do_cast<Target, src>
1811 >::type caster_type;
1813 return caster_type::lexical_cast_impl(arg);
1818 // call-by-value fallback version (deprecated)
1820 template<typename Target, typename Source>
1821 Target lexical_cast(Source arg)
1823 typedef typename detail::widest_char<
1824 BOOST_DEDUCED_TYPENAME detail::stream_char<Target>::type
1825 , BOOST_DEDUCED_TYPENAME detail::stream_char<Source>::type
1828 typedef std::char_traits<char_type> traits;
1829 detail::lexical_stream<Target, Source, traits> interpreter;
1832 if(!(interpreter << arg && interpreter >> result))
1833 BOOST_LCAST_THROW_BAD_CAST(Source, Target);
1840 // Copyright Kevlin Henney, 2000-2005.
1841 // Copyright Alexander Nasonov, 2006-2010.
1842 // Copyright Antony Polukhin, 2011.
1844 // Distributed under the Boost Software License, Version 1.0. (See
1845 // accompanying file LICENSE_1_0.txt or copy at
1846 // http://www.boost.org/LICENSE_1_0.txt)
1848 #undef BOOST_LCAST_NO_WCHAR_T