]> git.lyx.org Git - lyx.git/blob - boost/boost/lexical_cast.hpp
indices -> indexes.
[lyx.git] / boost / boost / lexical_cast.hpp
1 #ifndef BOOST_LEXICAL_CAST_INCLUDED
2 #define BOOST_LEXICAL_CAST_INCLUDED
3
4 // Boost lexical_cast.hpp header  -------------------------------------------//
5 //
6 // See http://www.boost.org/libs/conversion for documentation.
7 // See end of this header for rights and permissions.
8 //
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
16
17 #include <climits>
18 #include <cstddef>
19 #include <istream>
20 #include <locale>
21 #include <string>
22 #include <typeinfo>
23 #include <boost/config.hpp>
24 #include <boost/limits.hpp>
25 #include <boost/mpl/if.hpp>
26 #include <boost/throw_exception.hpp>
27 #include <boost/type_traits/is_pointer.hpp>
28 #include <boost/call_traits.hpp>
29 #include <boost/static_assert.hpp>
30 #include <boost/detail/lcast_precision.hpp>
31
32 #ifdef BOOST_NO_STRINGSTREAM
33 #include <strstream>
34 #else
35 #include <sstream>
36 #endif
37
38 #if defined(BOOST_NO_STRINGSTREAM) || \
39     defined(BOOST_NO_STD_WSTRING) || \
40     defined(BOOST_NO_STD_LOCALE) 
41 #define DISABLE_WIDE_CHAR_SUPPORT
42 #endif
43
44 namespace boost
45 {
46     // exception used to indicate runtime lexical_cast failure
47     class bad_lexical_cast : public std::bad_cast
48     {
49     public:
50         bad_lexical_cast() :
51         source(&typeid(void)), target(&typeid(void))
52         {
53         }
54         bad_lexical_cast(
55             const std::type_info &source_type_arg,
56             const std::type_info &target_type_arg) :
57             source(&source_type_arg), target(&target_type_arg)
58         {
59         }
60         const std::type_info &source_type() const
61         {
62             return *source;
63         }
64         const std::type_info &target_type() const
65         {
66             return *target;
67         }
68         virtual const char *what() const throw()
69         {
70             return "bad lexical cast: "
71                    "source type value could not be interpreted as target";
72         }
73         virtual ~bad_lexical_cast() throw()
74         {
75         }
76     private:
77         const std::type_info *source;
78         const std::type_info *target;
79     };
80
81     namespace detail // selectors for choosing stream character type
82     {
83         template<typename Type>
84         struct stream_char
85         {
86             typedef char type;
87         };
88
89 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
90         template<class CharT, class Traits, class Alloc>
91         struct stream_char< std::basic_string<CharT,Traits,Alloc> >
92         {
93             typedef CharT type;
94         };
95 #endif
96
97 #ifndef DISABLE_WIDE_CHAR_SUPPORT
98 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
99         template<>
100         struct stream_char<wchar_t>
101         {
102             typedef wchar_t type;
103         };
104 #endif
105
106         template<>
107         struct stream_char<wchar_t *>
108         {
109             typedef wchar_t type;
110         };
111
112         template<>
113         struct stream_char<const wchar_t *>
114         {
115             typedef wchar_t type;
116         };
117
118 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
119         template<>
120         struct stream_char<std::wstring>
121         {
122             typedef wchar_t type;
123         };
124 #endif
125 #endif
126
127         template<typename TargetChar, typename SourceChar>
128         struct widest_char
129         {
130             typedef TargetChar type;
131         };
132
133         template<>
134         struct widest_char<char, wchar_t>
135         {
136             typedef wchar_t type;
137         };
138     }
139
140     namespace detail // deduce_char_traits template
141     {
142 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
143         template<class CharT, class Target, class Source>
144         struct deduce_char_traits
145         {
146             typedef std::char_traits<CharT> type;
147         };
148
149         template<class CharT, class Traits, class Alloc, class Source>
150         struct deduce_char_traits< CharT
151                                  , std::basic_string<CharT,Traits,Alloc>
152                                  , Source
153                                  >
154         {
155             typedef Traits type;
156         };
157
158         template<class CharT, class Target, class Traits, class Alloc>
159         struct deduce_char_traits< CharT
160                                  , Target
161                                  , std::basic_string<CharT,Traits,Alloc>
162                                  >
163         {
164             typedef Traits type;
165         };
166
167         template<class CharT, class Traits, class Alloc1, class Alloc2>
168         struct deduce_char_traits< CharT
169                                  , std::basic_string<CharT,Traits,Alloc1>
170                                  , std::basic_string<CharT,Traits,Alloc2>
171                                  >
172         {
173             typedef Traits type;
174         };
175 #endif
176     }
177
178     namespace detail // lcast_src_length
179     {
180         // Return max. length of string representation of Source;
181         // 0 if unlimited (with exceptions for some types, see below).
182         // Values with limited string representation are placed to
183         // the buffer locally defined in lexical_cast function.
184         // 1 is returned for few types such as CharT const* or
185         // std::basic_string<CharT> that already have an internal
186         // buffer ready to be reused by lexical_stream_limited_src.
187         // Each specialization should have a correspondent operator<<
188         // defined in lexical_stream_limited_src.
189         template< class CharT  // A result of widest_char transformation.
190                 , class Source // Source type of lexical_cast.
191                 >
192         struct lcast_src_length
193         {
194             BOOST_STATIC_CONSTANT(std::size_t, value = 0);
195             // To check coverage, build the test with
196             // bjam --v2 profile optimization=off
197             static void check_coverage() {}
198         };
199
200         template<>
201         struct lcast_src_length<char, bool>
202         {
203             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
204             static void check_coverage() {}
205         };
206
207         template<>
208         struct lcast_src_length<char, char>
209         {
210             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
211             static void check_coverage() {}
212         };
213
214         // No specializations for:
215         // lcast_src_length<char, signed char>
216         // lcast_src_length<char, unsigned char>
217         // lcast_src_length<char, signed char*>
218         // lcast_src_length<char, unsigned char*>
219         // lcast_src_length<char, signed char const*>
220         // lcast_src_length<char, unsigned char const*>
221
222 #ifndef DISABLE_WIDE_CHAR_SUPPORT
223         template<>
224         struct lcast_src_length<wchar_t, bool>
225         {
226             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
227             static void check_coverage() {}
228         };
229
230         template<>
231         struct lcast_src_length<wchar_t, char>
232         {
233             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
234             static void check_coverage() {}
235         };
236
237 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
238         template<>
239         struct lcast_src_length<wchar_t, wchar_t>
240         {
241             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
242             static void check_coverage() {}
243         };
244 #endif
245 #endif
246
247         template<>
248         struct lcast_src_length<char, char const*>
249         {
250             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
251             static void check_coverage() {}
252         };
253
254         template<>
255         struct lcast_src_length<char, char*>
256         {
257             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
258             static void check_coverage() {}
259         };
260
261 #ifndef DISABLE_WIDE_CHAR_SUPPORT
262         template<>
263         struct lcast_src_length<wchar_t, wchar_t const*>
264         {
265             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
266             static void check_coverage() {}
267         };
268
269         template<>
270         struct lcast_src_length<wchar_t, wchar_t*>
271         {
272             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
273             static void check_coverage() {}
274         };
275 #endif
276
277 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
278         template<class CharT, class Traits, class Alloc>
279         struct lcast_src_length< CharT, std::basic_string<CharT,Traits,Alloc> >
280         {
281             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
282             static void check_coverage() {}
283         };
284 #else
285         template<>
286         struct lcast_src_length< char, std::basic_string<char> >
287         {
288             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
289             static void check_coverage() {}
290         };
291
292 #ifndef DISABLE_WIDE_CHAR_SUPPORT
293         template<>
294         struct lcast_src_length< wchar_t, std::basic_string<wchar_t> >
295         {
296             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
297             static void check_coverage() {}
298         };
299 #endif
300 #endif
301
302         // Helper for integral types.
303         // Notes on length calculation:
304         // Max length for 32bit int with grouping "\1" and thousands_sep ',':
305         // "-2,1,4,7,4,8,3,6,4,7"
306         //  ^                    - is_signed
307         //   ^                   - 1 digit not counted by digits10
308         //    ^^^^^^^^^^^^^^^^^^ - digits10 * 2
309         //
310         // Constant is_specialized is used instead of constant 1
311         // to prevent buffer overflow in a rare case when
312         // <boost/limits.hpp> doesn't add missing specialization for
313         // numeric_limits<T> for some integral type T.
314         // When is_specialized is false, the whole expression is 0.
315         template<class Source>
316         struct lcast_src_length_integral
317         {
318 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
319             BOOST_STATIC_CONSTANT(std::size_t, value =
320                   std::numeric_limits<Source>::is_signed +
321                   std::numeric_limits<Source>::is_specialized + // == 1
322                   std::numeric_limits<Source>::digits10 * 2
323               );
324 #else
325             BOOST_STATIC_CONSTANT(std::size_t, value = 156);
326             BOOST_STATIC_ASSERT(sizeof(Source) * CHAR_BIT <= 256);
327 #endif
328         };
329
330 #define BOOST_AUX_LEXICAL_CAST_DEF1(CharT, T) template<>             \
331     struct lcast_src_length<CharT, T> : lcast_src_length_integral<T> \
332     { static void check_coverage() {} };
333
334 #ifdef DISABLE_WIDE_CHAR_SUPPORT
335 #define BOOST_AUX_LEXICAL_CAST_DEF(T) BOOST_AUX_LEXICAL_CAST_DEF1(char, T)
336 #else
337 #define BOOST_AUX_LEXICAL_CAST_DEF(T)          \
338         BOOST_AUX_LEXICAL_CAST_DEF1(char, T)   \
339         BOOST_AUX_LEXICAL_CAST_DEF1(wchar_t, T)
340 #endif
341
342         BOOST_AUX_LEXICAL_CAST_DEF(short)
343         BOOST_AUX_LEXICAL_CAST_DEF(unsigned short)
344         BOOST_AUX_LEXICAL_CAST_DEF(int)
345         BOOST_AUX_LEXICAL_CAST_DEF(unsigned int)
346         BOOST_AUX_LEXICAL_CAST_DEF(long)
347         BOOST_AUX_LEXICAL_CAST_DEF(unsigned long)
348 #if defined(BOOST_HAS_LONG_LONG)
349         BOOST_AUX_LEXICAL_CAST_DEF(boost::ulong_long_type)
350         BOOST_AUX_LEXICAL_CAST_DEF(boost::long_long_type )
351 #elif defined(BOOST_HAS_MS_INT64)
352         BOOST_AUX_LEXICAL_CAST_DEF(unsigned __int64)
353         BOOST_AUX_LEXICAL_CAST_DEF(         __int64)
354 #endif
355
356 #undef BOOST_AUX_LEXICAL_CAST_DEF
357 #undef BOOST_AUX_LEXICAL_CAST_DEF1
358
359 #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
360         // Helper for floating point types.
361         // -1.23456789e-123456
362         // ^                   sign
363         //  ^                  leading digit
364         //   ^                 decimal point 
365         //    ^^^^^^^^         lcast_precision<Source>::value
366         //            ^        "e"
367         //             ^       exponent sign
368         //              ^^^^^^ exponent (assumed 6 or less digits)
369         // sign + leading digit + decimal point + "e" + exponent sign == 5
370         template<class Source>
371         struct lcast_src_length_floating
372         {
373             BOOST_STATIC_ASSERT(
374                     std::numeric_limits<Source>::max_exponent10 <=  999999L &&
375                     std::numeric_limits<Source>::min_exponent10 >= -999999L
376                 );
377             BOOST_STATIC_CONSTANT(std::size_t, value =
378                     5 + lcast_precision<Source>::value + 6
379                 );
380         };
381
382         template<>
383         struct lcast_src_length<char,float>
384           : lcast_src_length_floating<float>
385         {
386             static void check_coverage() {}
387         };
388
389         template<>
390         struct lcast_src_length<char,double>
391           : lcast_src_length_floating<double>
392         {
393             static void check_coverage() {}
394         };
395
396         template<>
397         struct lcast_src_length<char,long double>
398           : lcast_src_length_floating<long double>
399         {
400             static void check_coverage() {}
401         };
402
403 #ifndef DISABLE_WIDE_CHAR_SUPPORT
404     template<>
405     struct lcast_src_length<wchar_t,float>
406       : lcast_src_length_floating<float>
407     {
408         static void check_coverage() {}
409     };
410
411     template<>
412     struct lcast_src_length<wchar_t,double>
413       : lcast_src_length_floating<double>
414     {
415         static void check_coverage() {}
416     };
417
418     template<>
419     struct lcast_src_length<wchar_t,long double>
420       : lcast_src_length_floating<long double>
421     {
422         static void check_coverage() {}
423     };
424
425 #endif // #ifndef DISABLE_WIDE_CHAR_SUPPORT
426 #endif // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
427     }
428
429     namespace detail // '0' and '-' constants
430     {
431         template<typename CharT> struct lcast_char_constants;
432
433         template<>
434         struct lcast_char_constants<char>
435         {
436             BOOST_STATIC_CONSTANT(char, zero  = '0');
437             BOOST_STATIC_CONSTANT(char, minus = '-');
438         };
439
440 #ifndef DISABLE_WIDE_CHAR_SUPPORT
441         template<>
442         struct lcast_char_constants<wchar_t>
443         {
444             BOOST_STATIC_CONSTANT(wchar_t, zero  = L'0');
445             BOOST_STATIC_CONSTANT(wchar_t, minus = L'-');
446         };
447 #endif
448     }
449
450     namespace detail // lexical_streambuf_fake
451     {
452         struct lexical_streambuf_fake
453         {
454         };
455     }
456
457     namespace detail // lcast_to_unsigned
458     {
459 #if (defined _MSC_VER)
460 # pragma warning( push )
461 // C4146: unary minus operator applied to unsigned type, result still unsigned
462 # pragma warning( disable : 4146 )
463 #endif
464
465         inline unsigned int lcast_to_unsigned(int value)
466         {
467             unsigned int uval = value;
468             return value < 0 ? -uval : uval;
469         }
470
471         inline unsigned long lcast_to_unsigned(long value)
472         {
473             unsigned long uval = value;
474             return value < 0 ? -uval : uval;
475         }
476
477 #if defined(BOOST_HAS_LONG_LONG)
478         inline boost::ulong_long_type lcast_to_unsigned(boost::long_long_type v)
479         {
480             boost::ulong_long_type uval = v;
481             return v < 0 ? -uval : uval;
482         }
483 #elif defined(BOOST_HAS_MS_INT64)
484         inline unsigned __int64 lcast_to_unsigned(__int64 value)
485         {
486             unsigned __int64 uval = value;
487             return value < 0 ? -uval : uval;
488         }
489 #endif
490
491 #if (defined _MSC_VER)
492 # pragma warning( pop ) // C4146: unary minus operator applied to unsigned type,
493                         // result still unsigned
494 #endif
495     }
496
497     namespace detail // lcast_put_unsigned
498     {
499         template<class Traits, class T, class CharT>
500         CharT* lcast_put_unsigned(T n, CharT* finish)
501         {
502 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
503             BOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_signed);
504 #endif
505             CharT thousands_sep = 0;
506
507 #ifdef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
508             char const* grouping = "";
509             std::size_t const grouping_size = 0;
510 #else
511             std::locale loc;
512             typedef std::numpunct<CharT> numpunct;
513             numpunct const& np = BOOST_USE_FACET(numpunct, loc);
514             std::string const& grouping = np.grouping();
515             std::string::size_type const grouping_size = grouping.size();
516
517             if(grouping_size)
518                 thousands_sep = np.thousands_sep();
519 #endif
520
521             std::string::size_type group = 0; // current group number
522             char last_grp_size = grouping[0] <= 0 ? CHAR_MAX : grouping[0];
523             // a) Since grouping is const, grouping[grouping.size()] returns 0.
524             // b) It's safe to assume here and below that CHAR_MAX
525             //    is equivalent to unlimited grouping:
526 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
527             BOOST_STATIC_ASSERT(std::numeric_limits<T>::digits10 < CHAR_MAX);
528 #endif
529             typedef typename Traits::int_type int_type;
530             CharT const czero = lcast_char_constants<CharT>::zero;
531             int_type const zero = Traits::to_int_type(czero);
532
533             char left = last_grp_size;
534
535             do
536             {
537                 if(left == 0)
538                 {
539                     ++group;
540                     if(group < grouping_size)
541                     {
542                         char const grp_size = grouping[group];
543                         last_grp_size = grp_size <= 0 ? CHAR_MAX : grp_size;
544                     }
545
546                     left = last_grp_size;
547                     --finish;
548                     Traits::assign(*finish, thousands_sep);
549                 }
550
551                 --left;
552                 --finish;
553                 int_type const digit = static_cast<int_type>(n % 10U);
554                 Traits::assign(*finish, Traits::to_char_type(zero + digit));
555                 n /= 10;
556             } while(n);
557
558             return finish;
559         }
560     }
561
562     namespace detail // stream wrapper for handling lexical conversions
563     {
564         template<typename Target, typename Source, typename Traits>
565         class lexical_stream
566         {
567         private:
568             typedef typename widest_char<
569                 typename stream_char<Target>::type,
570                 typename stream_char<Source>::type>::type char_type;
571
572             typedef Traits traits_type;
573
574         public:
575             lexical_stream(char_type* = 0, char_type* = 0)
576             {
577                 stream.unsetf(std::ios::skipws);
578                 lcast_set_precision(stream, (Source*)0, (Target*)0);
579             }
580             ~lexical_stream()
581             {
582                 #if defined(BOOST_NO_STRINGSTREAM)
583                 stream.freeze(false);
584                 #endif
585             }
586             bool operator<<(const Source &input)
587             {
588                 return !(stream << input).fail();
589             }
590             template<typename InputStreamable>
591             bool operator>>(InputStreamable &output)
592             {
593                 return !is_pointer<InputStreamable>::value &&
594                        stream >> output &&
595                        stream.get() ==
596 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
597 // GCC 2.9x lacks std::char_traits<>::eof().
598 // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
599 // configurations, which do provide std::char_traits<>::eof().
600     
601                            EOF;
602 #else
603                            traits_type::eof();
604 #endif
605             }
606
607 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
608
609             bool operator>>(std::string &output)
610             {
611                 #if defined(BOOST_NO_STRINGSTREAM)
612                 stream << '\0';
613                 #endif
614                 stream.str().swap(output);
615                 return true;
616             }
617             #ifndef DISABLE_WIDE_CHAR_SUPPORT
618             bool operator>>(std::wstring &output)
619             {
620                 stream.str().swap(output);
621                 return true;
622             }
623             #endif
624
625 #else
626             bool operator>>(std::basic_string<char_type,traits_type>& output)
627             {
628                 stream.str().swap(output);
629                 return true;
630             }
631
632             template<class Alloc>
633             bool operator>>(std::basic_string<char_type,traits_type,Alloc>& out)
634             {
635                 std::basic_string<char_type,traits_type> str(stream.str());
636                 out.assign(str.begin(), str.end());
637                 return true;
638             }
639 #endif
640         private:
641             #if defined(BOOST_NO_STRINGSTREAM)
642             std::strstream stream;
643             #elif defined(BOOST_NO_STD_LOCALE)
644             std::stringstream stream;
645             #else
646             std::basic_stringstream<char_type,traits_type> stream;
647             #endif
648         };
649     }
650
651     namespace detail // optimized stream wrapper
652     {
653         // String representation of Source has an upper limit.
654         template< class CharT // a result of widest_char transformation
655                 , class Base // lexical_streambuf_fake or basic_streambuf<CharT>
656                 , class Traits // usually char_traits<CharT>
657                 >
658         class lexical_stream_limited_src : public Base
659         {
660             // A string representation of Source is written to [start, finish).
661             // Currently, it is assumed that [start, finish) is big enough
662             // to hold a string representation of any Source value.
663             CharT* start;
664             CharT* finish;
665
666         private:
667
668             static void widen_and_assign(char*p, char ch)
669             {
670                 Traits::assign(*p, ch);
671             }
672
673 #ifndef DISABLE_WIDE_CHAR_SUPPORT
674             static void widen_and_assign(wchar_t* p, char ch)
675             {
676                 std::locale loc;
677                 wchar_t w = BOOST_USE_FACET(std::ctype<wchar_t>, loc).widen(ch);
678                 Traits::assign(*p, w);
679             }
680
681             static void widen_and_assign(wchar_t* p, wchar_t ch)
682             {
683                 Traits::assign(*p, ch);
684             }
685
686             static void widen_and_assign(char*, wchar_t ch); // undefined
687 #endif
688
689             template<class OutputStreamable>
690             bool lcast_put(const OutputStreamable& input)
691             {
692                 this->setp(start, finish);
693                 std::basic_ostream<CharT> stream(static_cast<Base*>(this));
694                 lcast_set_precision(stream, (OutputStreamable*)0);
695                 bool const result = !(stream << input).fail();
696                 finish = this->pptr();
697                 return result;
698             }
699
700             // Undefined:
701             lexical_stream_limited_src(lexical_stream_limited_src const&);
702             void operator=(lexical_stream_limited_src const&);
703
704         public:
705
706             lexical_stream_limited_src(CharT* start, CharT* finish)
707               : start(start)
708               , finish(finish)
709             {}
710
711         public: // output
712
713             template<class Alloc>
714             bool operator<<(std::basic_string<CharT,Traits,Alloc> const& str)
715             {
716                 start = const_cast<CharT*>(str.data());
717                 finish = start + str.length();
718                 return true;
719             }
720
721             bool operator<<(bool);
722             bool operator<<(char);
723 #if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
724             bool operator<<(wchar_t);
725 #endif
726             bool operator<<(CharT const*);
727             bool operator<<(short);
728             bool operator<<(int);
729             bool operator<<(long);
730             bool operator<<(unsigned short);
731             bool operator<<(unsigned int);
732             bool operator<<(unsigned long);
733 #if defined(BOOST_HAS_LONG_LONG)
734             bool operator<<(boost::ulong_long_type);
735             bool operator<<(boost::long_long_type );
736 #elif defined(BOOST_HAS_MS_INT64)
737             bool operator<<(unsigned __int64);
738             bool operator<<(         __int64);
739 #endif
740             // These three operators use ostream and streambuf.
741             // lcast_streambuf_for_source<T>::value is true.
742             bool operator<<(float);
743             bool operator<<(double);
744             bool operator<<(long double);
745
746         public: // input
747
748             // Generic istream-based algorithm.
749             // lcast_streambuf_for_target<InputStreamable>::value is true.
750             template<typename InputStreamable>
751             bool operator>>(InputStreamable& output)
752             {
753 #if (defined _MSC_VER)
754 # pragma warning( push )
755   // conditional expression is constant
756 # pragma warning( disable : 4127 )
757 #endif
758                 if(is_pointer<InputStreamable>::value)
759                     return false;
760
761                 this->setg(start, start, finish);
762                 std::basic_istream<CharT> stream(static_cast<Base*>(this));
763                 stream.unsetf(std::ios::skipws);
764                 lcast_set_precision(stream, (InputStreamable*)0);
765 #if (defined _MSC_VER)
766 # pragma warning( pop )
767 #endif
768                 return stream >> output &&
769                     stream.get() ==
770 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
771         // GCC 2.9x lacks std::char_traits<>::eof().
772         // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
773         // configurations, which do provide std::char_traits<>::eof().
774
775                     EOF;
776 #else
777                 Traits::eof();
778 #endif
779             }
780
781             bool operator>>(CharT&);
782
783 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
784 // This #if is in sync with lcast_streambuf_for_target
785
786             bool operator>>(std::string&);
787
788 #ifndef DISABLE_WIDE_CHAR_SUPPORT
789             bool operator>>(std::wstring&);
790 #endif
791
792 #else
793             template<class Alloc>
794             bool operator>>(std::basic_string<CharT,Traits,Alloc>& str)
795             {
796                 str.assign(start, finish);
797                 return true;
798             }
799 #endif
800         };
801
802         template<typename CharT, class Base, class Traits>
803         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
804                 bool value)
805         {
806             typedef typename Traits::int_type int_type;
807             CharT const czero = lcast_char_constants<CharT>::zero;
808             int_type const zero = Traits::to_int_type(czero);
809             Traits::assign(*start, Traits::to_char_type(zero + value));
810             finish = start + 1;
811             return true;
812         }
813
814         template<typename CharT, class Base, class Traits>
815         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
816                 char ch)
817         {
818             widen_and_assign(start, ch);
819             finish = start + 1;
820             return true;
821         }
822
823 #if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
824         template<typename CharT, class Base, class Traits>
825         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
826                 wchar_t ch)
827         {
828             widen_and_assign(start, ch);
829             finish = start + 1;
830             return true;
831         }
832 #endif
833
834         template<typename CharT, class Base, class Traits>
835         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
836                 short n)
837         {
838             start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
839             if(n < 0)
840             {
841                 --start;
842                 CharT const minus = lcast_char_constants<CharT>::minus;
843                 Traits::assign(*start, minus);
844             }
845             return true;
846         }
847
848         template<typename CharT, class Base, class Traits>
849         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
850                 int n)
851         {
852             start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
853             if(n < 0)
854             {
855                 --start;
856                 CharT const minus = lcast_char_constants<CharT>::minus;
857                 Traits::assign(*start, minus);
858             }
859             return true;
860         }
861
862         template<typename CharT, class Base, class Traits>
863         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
864                 long n)
865         {
866             start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
867             if(n < 0)
868             {
869                 --start;
870                 CharT const minus = lcast_char_constants<CharT>::minus;
871                 Traits::assign(*start, minus);
872             }
873             return true;
874         }
875
876 #if defined(BOOST_HAS_LONG_LONG)
877         template<typename CharT, class Base, class Traits>
878         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
879                 boost::long_long_type n)
880         {
881             start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
882             if(n < 0)
883             {
884                 --start;
885                 CharT const minus = lcast_char_constants<CharT>::minus;
886                 Traits::assign(*start, minus);
887             }
888             return true;
889         }
890 #elif defined(BOOST_HAS_MS_INT64)
891         template<typename CharT, class Base, class Traits>
892         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
893                 __int64 n)
894         {
895             start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
896             if(n < 0)
897             {
898                 --start;
899                 CharT const minus = lcast_char_constants<CharT>::minus;
900                 Traits::assign(*start, minus);
901             }
902             return true;
903         }
904 #endif
905
906         template<typename CharT, class Base, class Traits>
907         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
908                 unsigned short n)
909         {
910             start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
911             return true;
912         }
913
914         template<typename CharT, class Base, class Traits>
915         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
916                 unsigned int n)
917         {
918             start = lcast_put_unsigned<Traits>(n, finish);
919             return true;
920         }
921
922         template<typename CharT, class Base, class Traits>
923         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
924                 unsigned long n)
925         {
926             start = lcast_put_unsigned<Traits>(n, finish);
927             return true;
928         }
929
930 #if defined(BOOST_HAS_LONG_LONG)
931         template<typename CharT, class Base, class Traits>
932         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
933                 boost::ulong_long_type n)
934         {
935             start = lcast_put_unsigned<Traits>(n, finish);
936             return true;
937         }
938 #elif defined(BOOST_HAS_MS_INT64)
939         template<typename CharT, class Base, class Traits>
940         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
941                 unsigned __int64 n)
942         {
943             start = lcast_put_unsigned<Traits>(n, finish);
944             return true;
945         }
946 #endif
947
948         template<typename CharT, class Base, class Traits>
949         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
950                 float val)
951         {
952             return this->lcast_put(val);
953         }
954
955         template<typename CharT, class Base, class Traits>
956         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
957                 double val)
958         {
959             return this->lcast_put(val);
960         }
961
962         template<typename CharT, class Base, class Traits>
963         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
964                 long double val)
965         {
966             return this->lcast_put(val);
967         }
968
969         template<typename CharT, class Base, class Traits>
970         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
971                 CharT const* str)
972         {
973             start = const_cast<CharT*>(str);
974             finish = start + Traits::length(str);
975             return true;
976         }
977
978         template<typename CharT, class Base, class Traits>
979         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
980                 CharT& output)
981         {
982             bool const ok = (finish - start == 1);
983             if(ok)
984                 Traits::assign(output, *start);
985             return ok;
986         }
987
988 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
989         template<typename CharT, class Base, class Traits>
990         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
991                 std::string& str)
992         {
993             str.assign(start, finish);
994             return true;
995         }
996
997 #ifndef DISABLE_WIDE_CHAR_SUPPORT
998         template<typename CharT, class Base, class Traits>
999         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
1000                 std::wstring& str)
1001         {
1002             str.assign(start, finish);
1003             return true;
1004         }
1005 #endif
1006 #endif
1007     }
1008
1009     namespace detail // lcast_streambuf_for_source
1010     {
1011         // Returns true if optimized stream wrapper needs ostream for writing.
1012         template<class Source>
1013         struct lcast_streambuf_for_source
1014         {
1015             BOOST_STATIC_CONSTANT(bool, value = false);
1016         };
1017
1018         template<>
1019         struct lcast_streambuf_for_source<float>
1020         {
1021             BOOST_STATIC_CONSTANT(bool, value = true);
1022         };
1023  
1024         template<>
1025         struct lcast_streambuf_for_source<double>
1026         {
1027             BOOST_STATIC_CONSTANT(bool, value = true);
1028         };
1029   
1030         template<>
1031         struct lcast_streambuf_for_source<long double>
1032         {
1033             BOOST_STATIC_CONSTANT(bool, value = true);
1034         };
1035     }
1036
1037     namespace detail // lcast_streambuf_for_target
1038     {
1039         // Returns true if optimized stream wrapper needs istream for reading.
1040         template<class Target>
1041         struct lcast_streambuf_for_target
1042         {
1043             BOOST_STATIC_CONSTANT(bool, value = true);
1044         };
1045
1046         template<>
1047         struct lcast_streambuf_for_target<char>
1048         {
1049             BOOST_STATIC_CONSTANT(bool, value = false);
1050         };
1051
1052 #if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
1053         template<>
1054         struct lcast_streambuf_for_target<wchar_t>
1055         {
1056             BOOST_STATIC_CONSTANT(bool, value = false);
1057         };
1058 #endif
1059
1060 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1061         template<class Traits, class Alloc>
1062         struct lcast_streambuf_for_target<
1063                     std::basic_string<char,Traits,Alloc> >
1064         {
1065             BOOST_STATIC_CONSTANT(bool, value = false);
1066         };
1067
1068 #ifndef DISABLE_WIDE_CHAR_SUPPORT
1069         template<class Traits, class Alloc>
1070         struct lcast_streambuf_for_target<
1071                     std::basic_string<wchar_t,Traits,Alloc> >
1072         {
1073             BOOST_STATIC_CONSTANT(bool, value = false);
1074         };
1075 #endif
1076 #else
1077         template<>
1078         struct lcast_streambuf_for_target<std::string>
1079         {
1080             BOOST_STATIC_CONSTANT(bool, value = false);
1081         };
1082
1083 #ifndef DISABLE_WIDE_CHAR_SUPPORT
1084         template<>
1085         struct lcast_streambuf_for_target<std::wstring>
1086         {
1087             BOOST_STATIC_CONSTANT(bool, value = false);
1088         };
1089 #endif
1090 #endif
1091     }
1092
1093     #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1094
1095     // call-by-const reference version
1096
1097     namespace detail
1098     {
1099         template<class T>
1100         struct array_to_pointer_decay
1101         {
1102             typedef T type;
1103         };
1104
1105         template<class T, std::size_t N>
1106         struct array_to_pointer_decay<T[N]>
1107         {
1108             typedef const T * type;
1109         };
1110
1111         template< typename Target
1112                 , typename Source
1113                 , bool Unlimited // string representation of Source is unlimited
1114                 , typename CharT
1115                 >
1116         Target lexical_cast(
1117             BOOST_DEDUCED_TYPENAME boost::call_traits<Source>::param_type arg,
1118             CharT* buf, std::size_t src_len)
1119         {
1120             typedef BOOST_DEDUCED_TYPENAME
1121                 deduce_char_traits<CharT,Target,Source>::type traits;
1122
1123             typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
1124                 lcast_streambuf_for_target<Target>::value ||
1125                 lcast_streambuf_for_source<Source>::value
1126               , std::basic_streambuf<CharT>
1127               , lexical_streambuf_fake
1128               >::type base;
1129
1130             BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
1131                 Unlimited
1132               , detail::lexical_stream<Target,Source,traits>
1133               , detail::lexical_stream_limited_src<CharT,base,traits>
1134               >::type interpreter(buf, buf + src_len);
1135
1136             // The original form, reproduced below, is more elegant
1137             // but yields a spurious C4701 warning ("possible use of
1138             // "result" before initialization") with VC7.1 (/W4).
1139 //
1140 //            Target result;
1141 //
1142 //            if(!(interpreter << arg && interpreter >> result))
1143 //                throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)));
1144 //            return result;
1145
1146             if(interpreter << arg) {
1147                 Target result;
1148                 if (interpreter >> result)
1149                     return result;
1150             }
1151             throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)));
1152             return Target(); // normally never reached (throw_exception)
1153         }
1154     }
1155
1156     template<typename Target, typename Source>
1157     inline Target lexical_cast(const Source &arg)
1158     {
1159         typedef typename detail::array_to_pointer_decay<Source>::type src;
1160
1161         typedef typename detail::widest_char<
1162             typename detail::stream_char<Target>::type
1163           , typename detail::stream_char<src>::type
1164           >::type char_type;
1165
1166         typedef detail::lcast_src_length<char_type, src> lcast_src_length;
1167         std::size_t const src_len = lcast_src_length::value;
1168         char_type buf[src_len + 1];
1169         lcast_src_length::check_coverage();
1170         return detail::lexical_cast<Target, src, !src_len>(arg, buf, src_len);
1171     }
1172
1173     #else
1174
1175     // call-by-value fallback version (deprecated)
1176
1177     template<typename Target, typename Source>
1178     Target lexical_cast(Source arg)
1179     {
1180         typedef typename detail::widest_char< 
1181             BOOST_DEDUCED_TYPENAME detail::stream_char<Target>::type 
1182           , BOOST_DEDUCED_TYPENAME detail::stream_char<Source>::type 
1183         >::type char_type; 
1184
1185         typedef std::char_traits<char_type> traits;
1186         detail::lexical_stream<Target, Source, traits> interpreter;
1187         Target result;
1188
1189         if(!(interpreter << arg && interpreter >> result))
1190             throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)));
1191         return result;
1192     }
1193
1194     #endif
1195 }
1196
1197 // Copyright Kevlin Henney, 2000-2005.
1198 // Copyright Alexander Nasonov, 2006-2007.
1199 //
1200 // Distributed under the Boost Software License, Version 1.0. (See
1201 // accompanying file LICENSE_1_0.txt or copy at
1202 // http://www.boost.org/LICENSE_1_0.txt)
1203
1204 #undef DISABLE_WIDE_CHAR_SUPPORT
1205 #endif