Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-19 09:47:37

0001 //  Copyright (c) 2001-2011 Hartmut Kaiser
0002 //
0003 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 #if !defined(BOOST_SPIRIT_KARMA_NUMERIC_UTILS_FEB_23_2007_0841PM)
0007 #define BOOST_SPIRIT_KARMA_NUMERIC_UTILS_FEB_23_2007_0841PM
0008 
0009 #if defined(_MSC_VER)
0010 #pragma once
0011 #endif
0012 
0013 #include <boost/config.hpp>
0014 #include <boost/config/no_tr1/cmath.hpp>
0015 #include <boost/limits.hpp>
0016 
0017 #include <boost/type_traits/is_integral.hpp>
0018 #include <boost/spirit/home/support/char_class.hpp>
0019 #include <boost/spirit/home/support/unused.hpp>
0020 #include <boost/spirit/home/support/numeric_traits.hpp>
0021 #include <boost/spirit/home/support/detail/pow10.hpp>
0022 #include <boost/spirit/home/karma/detail/generate_to.hpp>
0023 #include <boost/spirit/home/karma/detail/string_generate.hpp>
0024 
0025 #include <boost/core/cmath.hpp>
0026 
0027 ///////////////////////////////////////////////////////////////////////////////
0028 //
0029 //  The value BOOST_KARMA_NUMERICS_LOOP_UNROLL specifies, how to unroll the
0030 //  integer string generation loop (see below).
0031 //
0032 //      Set the value to some integer in between 0 (no unrolling) and the
0033 //      largest expected generated integer string length (complete unrolling).
0034 //      If not specified, this value defaults to 6.
0035 //
0036 ///////////////////////////////////////////////////////////////////////////////
0037 #if !defined(BOOST_KARMA_NUMERICS_LOOP_UNROLL)
0038 #define BOOST_KARMA_NUMERICS_LOOP_UNROLL 6
0039 #endif
0040 
0041 #if BOOST_KARMA_NUMERICS_LOOP_UNROLL < 0
0042 #error "Please set the BOOST_KARMA_NUMERICS_LOOP_UNROLL to a non-negative value!"
0043 #endif
0044 
0045 namespace boost { namespace spirit { namespace traits
0046 {
0047     ///////////////////////////////////////////////////////////////////////
0048     //
0049     //  return the absolute value from a given number, avoiding over- and
0050     //  underflow
0051     //
0052     ///////////////////////////////////////////////////////////////////////
0053     template <typename T, typename Enable/* = void*/>
0054     struct absolute_value
0055     {
0056         typedef T type;
0057         static T call (T n)
0058         {
0059             // allow for ADL to find the correct overloads for fabs
0060             using namespace std;
0061             return fabs(n);
0062         }
0063     };
0064 
0065 #define BOOST_SPIRIT_ABSOLUTE_VALUE(signedtype, unsignedtype)                 \
0066         template <>                                                           \
0067         struct absolute_value<signedtype>                                     \
0068         {                                                                     \
0069             typedef unsignedtype type;                                        \
0070             static type call(signedtype n)                                    \
0071             {                                                                 \
0072                 /* implementation is well-defined for one's complement, */    \
0073                 /* two's complement, and signed magnitude architectures */    \
0074                 /* by the C++ Standard. [conv.integral] [expr.unary.op] */    \
0075                 return (n >= 0) ?  static_cast<type>(n)                       \
0076                                 : -static_cast<type>(n);                      \
0077             }                                                                 \
0078         }                                                                     \
0079     /**/
0080 #define BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(unsignedtype)                    \
0081         template <>                                                           \
0082         struct absolute_value<unsignedtype>                                   \
0083         {                                                                     \
0084             typedef unsignedtype type;                                        \
0085             static type call(unsignedtype n)                                  \
0086             {                                                                 \
0087                 return n;                                                     \
0088             }                                                                 \
0089         }                                                                     \
0090     /**/
0091 
0092 #if defined(BOOST_MSVC)
0093 # pragma warning(push)
0094 // unary minus operator applied to unsigned type, result still unsigned
0095 # pragma warning(disable: 4146)
0096 #endif
0097     BOOST_SPIRIT_ABSOLUTE_VALUE(signed char, unsigned char);
0098     BOOST_SPIRIT_ABSOLUTE_VALUE(char, unsigned char);
0099     BOOST_SPIRIT_ABSOLUTE_VALUE(short, unsigned short);
0100     BOOST_SPIRIT_ABSOLUTE_VALUE(int, unsigned int);
0101     BOOST_SPIRIT_ABSOLUTE_VALUE(long, unsigned long);
0102     BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(unsigned char);
0103     BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(unsigned short);
0104     BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(unsigned int);
0105     BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(unsigned long);
0106 #ifdef BOOST_HAS_LONG_LONG
0107     BOOST_SPIRIT_ABSOLUTE_VALUE(boost::long_long_type, boost::ulong_long_type);
0108     BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(boost::ulong_long_type);
0109 #endif
0110 #if defined(BOOST_MSVC)
0111 # pragma warning(pop)
0112 #endif
0113 
0114 #undef BOOST_SPIRIT_ABSOLUTE_VALUE
0115 #undef BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED
0116 
0117     template <>
0118     struct absolute_value<float>
0119     {
0120         typedef float type;
0121         static type call(float n)
0122         {
0123             return (std::fabs)(n);
0124         }
0125     };
0126 
0127     template <>
0128     struct absolute_value<double>
0129     {
0130         typedef double type;
0131         static type call(double n)
0132         {
0133             return (std::fabs)(n);
0134         }
0135     };
0136 
0137     template <>
0138     struct absolute_value<long double>
0139     {
0140         typedef long double type;
0141         static type call(long double n)
0142         {
0143             return (std::fabs)(n);
0144         }
0145     };
0146 
0147     // specialization for pointers
0148     template <typename T>
0149     struct absolute_value<T*>
0150     {
0151         typedef std::size_t type;
0152         static type call (T* p)
0153         {
0154             return std::size_t(p);
0155         }
0156     };
0157 
0158     template <typename T>
0159     inline typename absolute_value<T>::type
0160     get_absolute_value(T n)
0161     {
0162         return absolute_value<T>::call(n);
0163     }
0164 
0165     ///////////////////////////////////////////////////////////////////////
0166     template <typename T, typename Enable/* = void*/>
0167     struct is_negative
0168     {
0169         static bool call(T n)
0170         {
0171             return (n < 0) ? true : false;
0172         }
0173     };
0174 
0175     template <>
0176     struct is_negative<float>
0177     {
0178         static bool call(float n)
0179         {
0180             return (core::signbit)(n) ? true : false;
0181         }
0182     };
0183 
0184     template <>
0185     struct is_negative<double>
0186     {
0187         static bool call(double n)
0188         {
0189             return (core::signbit)(n) ? true : false;
0190         }
0191     };
0192 
0193     template <>
0194     struct is_negative<long double>
0195     {
0196         static bool call(long double n)
0197         {
0198             return (core::signbit)(n) ? true : false;
0199         }
0200     };
0201 
0202     template <typename T>
0203     inline bool test_negative(T n)
0204     {
0205         return is_negative<T>::call(n);
0206     }
0207 
0208     ///////////////////////////////////////////////////////////////////////
0209     template <typename T, typename Enable/* = void*/>
0210     struct is_zero
0211     {
0212         static bool call(T n)
0213         {
0214             return (n == 0) ? true : false;
0215         }
0216     };
0217 
0218     template <>
0219     struct is_zero<float>
0220     {
0221         static bool call(float n)
0222         {
0223             return (core::fpclassify)(n) == core::fp_zero;
0224         }
0225     };
0226 
0227     template <>
0228     struct is_zero<double>
0229     {
0230         static bool call(double n)
0231         {
0232             return (core::fpclassify)(n) == core::fp_zero;
0233         }
0234     };
0235 
0236     template <>
0237     struct is_zero<long double>
0238     {
0239         static bool call(long double n)
0240         {
0241             return (core::fpclassify)(n) == core::fp_zero;
0242         }
0243     };
0244 
0245     template <typename T>
0246     inline bool test_zero(T n)
0247     {
0248         return is_zero<T>::call(n);
0249     }
0250 
0251     ///////////////////////////////////////////////////////////////////////
0252     template <typename T, typename Enable/* = void*/>
0253     struct is_nan
0254     {
0255         static bool call(T n)
0256         {
0257             // NaN numbers are not equal to anything
0258             return (n != n) ? true : false;
0259         }
0260     };
0261 
0262     template <>
0263     struct is_nan<float>
0264     {
0265         static bool call(float n)
0266         {
0267             return (core::fpclassify)(n) == core::fp_nan;
0268         }
0269     };
0270 
0271     template <>
0272     struct is_nan<double>
0273     {
0274         static bool call(double n)
0275         {
0276             return (core::fpclassify)(n) == core::fp_nan;
0277         }
0278     };
0279 
0280     template <>
0281     struct is_nan<long double>
0282     {
0283         static bool call(long double n)
0284         {
0285             return (core::fpclassify)(n) == core::fp_nan;
0286         }
0287     };
0288 
0289     template <typename T>
0290     inline bool test_nan(T n)
0291     {
0292         return is_nan<T>::call(n);
0293     }
0294 
0295     ///////////////////////////////////////////////////////////////////////
0296     template <typename T, typename Enable/* = void*/>
0297     struct is_infinite
0298     {
0299         static bool call(T n)
0300         {
0301             return std::numeric_limits<T>::has_infinity
0302                 && n == std::numeric_limits<T>::infinity();
0303         }
0304     };
0305 
0306     template <>
0307     struct is_infinite<float>
0308     {
0309         static bool call(float n)
0310         {
0311             return (core::fpclassify)(n) == core::fp_infinite;
0312         }
0313     };
0314 
0315     template <>
0316     struct is_infinite<double>
0317     {
0318         static bool call(double n)
0319         {
0320             return (core::fpclassify)(n) == core::fp_infinite;
0321         }
0322     };
0323 
0324     template <>
0325     struct is_infinite<long double>
0326     {
0327         static bool call(long double n)
0328         {
0329             return (core::fpclassify)(n) == core::fp_infinite;
0330         }
0331     };
0332 
0333     template <typename T>
0334     inline bool test_infinite(T n)
0335     {
0336         return is_infinite<T>::call(n);
0337     }
0338 
0339     ///////////////////////////////////////////////////////////////////////
0340     struct cast_to_long
0341     {
0342         static long call(float n, mpl::false_)
0343         {
0344             return static_cast<long>(std::floor(n));
0345         }
0346 
0347         static long call(double n, mpl::false_)
0348         {
0349             return static_cast<long>(std::floor(n));
0350         }
0351 
0352         static long call(long double n, mpl::false_)
0353         {
0354             return static_cast<long>(std::floor(n));
0355         }
0356 
0357         template <typename T>
0358         static long call(T n, mpl::false_)
0359         {
0360             // allow for ADL to find the correct overload for floor and
0361             // lround
0362             using namespace std;
0363             return lround(floor(n));
0364         }
0365 
0366         template <typename T>
0367         static long call(T n, mpl::true_)
0368         {
0369             return static_cast<long>(n);
0370         }
0371 
0372         template <typename T>
0373         static long call(T n)
0374         {
0375             return call(n, mpl::bool_<is_integral<T>::value>());
0376         }
0377     };
0378 
0379     ///////////////////////////////////////////////////////////////////////
0380     struct truncate_to_long
0381     {
0382         static long call(float n, mpl::false_)
0383         {
0384             return test_negative(n) ? static_cast<long>(std::ceil(n)) :
0385                 static_cast<long>(std::floor(n));
0386         }
0387 
0388         static long call(double n, mpl::false_)
0389         {
0390             return test_negative(n) ? static_cast<long>(std::ceil(n)) :
0391                 static_cast<long>(std::floor(n));
0392         }
0393 
0394         static long call(long double n, mpl::false_)
0395         {
0396             return test_negative(n) ? static_cast<long>(std::ceil(n)) :
0397                 static_cast<long>(std::floor(n));
0398         }
0399 
0400         template <typename T>
0401         static long call(T n, mpl::false_)
0402         {
0403             // allow for ADL to find the correct overloads for ltrunc
0404             using namespace std;
0405             return ltrunc(n);
0406         }
0407 
0408         template <typename T>
0409         static long call(T n, mpl::true_)
0410         {
0411             return static_cast<long>(n);
0412         }
0413 
0414         template <typename T>
0415         static long call(T n)
0416         {
0417             return call(n, mpl::bool_<is_integral<T>::value>());
0418         }
0419     };
0420 
0421     ///////////////////////////////////////////////////////////////////////
0422     //
0423     //  Traits class for radix specific number conversion
0424     //
0425     //      Convert a digit from binary representation to character
0426     //      representation:
0427     //
0428     //          static int call(unsigned n);
0429     //
0430     ///////////////////////////////////////////////////////////////////////
0431     namespace detail
0432     {
0433         template <typename CharEncoding, typename Tag, bool radix_less_than_10>
0434         struct convert_digit
0435         {
0436             static int call(unsigned n)
0437             {
0438                 if (n <= 9)
0439                     return n + '0';
0440 
0441                 using spirit::char_class::convert;
0442                 return convert<CharEncoding>::to(Tag(), n - 10 + 'a');
0443             }
0444         };
0445 
0446         template <>
0447         struct convert_digit<unused_type, unused_type, false>
0448         {
0449             static int call(unsigned n)
0450             {
0451                 if (n <= 9)
0452                     return n + '0';
0453                 return n - 10 + 'a';
0454             }
0455         };
0456 
0457         template <typename CharEncoding, typename Tag>
0458         struct convert_digit<CharEncoding, Tag, true>
0459         {
0460             static int call(unsigned n)
0461             {
0462                 return n + '0';
0463             }
0464         };
0465     }
0466 
0467     template <unsigned Radix, typename CharEncoding, typename Tag>
0468     struct convert_digit
0469       : detail::convert_digit<CharEncoding, Tag, (Radix <= 10) ? true : false>
0470     {};
0471 
0472     ///////////////////////////////////////////////////////////////////////
0473     template <unsigned Radix>
0474     struct divide
0475     {
0476         template <typename T>
0477         static T call(T& n, mpl::true_)
0478         {
0479             return n / Radix;
0480         }
0481 
0482         template <typename T>
0483         static T call(T& n, mpl::false_)
0484         {
0485             // Allow ADL to find the correct overload for floor
0486             using namespace std;
0487             return floor(n / Radix);
0488         }
0489 
0490         template <typename T>
0491         static T call(T& n, T const&, int)
0492         {
0493             return call(n, mpl::bool_<is_integral<T>::value>());
0494         }
0495 
0496         template <typename T>
0497         static T call(T& n)
0498         {
0499             return call(n, mpl::bool_<is_integral<T>::value>());
0500         }
0501     };
0502 
0503     // specialization for division by 10
0504     template <>
0505     struct divide<10>
0506     {
0507         template <typename T>
0508         static T call(T& n, T, int, mpl::true_)
0509         {
0510             return n / 10;
0511         }
0512 
0513         template <typename T>
0514         static T call(T, T& num, int exp, mpl::false_)
0515         {
0516             // Allow ADL to find the correct overload for floor
0517             using namespace std;
0518             return floor(num / spirit::traits::pow10<T>(exp));
0519         }
0520 
0521         template <typename T>
0522         static T call(T& n, T& num, int exp)
0523         {
0524             return call(n, num, exp, mpl::bool_<is_integral<T>::value>());
0525         }
0526 
0527         template <typename T>
0528         static T call(T& n)
0529         {
0530             return call(n, n, 1, mpl::bool_<is_integral<T>::value>());
0531         }
0532     };
0533 
0534     ///////////////////////////////////////////////////////////////////////
0535     template <unsigned Radix>
0536     struct remainder
0537     {
0538         template <typename T>
0539         static long call(T n, mpl::true_)
0540         {
0541             // this cast is safe since we know the result is not larger
0542             // than Radix
0543             return static_cast<long>(n % Radix);
0544         }
0545 
0546         template <typename T>
0547         static long call(T n, mpl::false_)
0548         {
0549             // Allow ADL to find the correct overload for fmod
0550             using namespace std;
0551             return cast_to_long::call(fmod(n, T(Radix)));
0552         }
0553 
0554         template <typename T>
0555         static long call(T n)
0556         {
0557             return call(n, mpl::bool_<is_integral<T>::value>());
0558         }
0559     };
0560 }}}
0561 
0562 namespace boost { namespace spirit { namespace karma
0563 {
0564     ///////////////////////////////////////////////////////////////////////////
0565     //
0566     //  The int_inserter template takes care of the integer to string
0567     //  conversion. If specified, the loop is unrolled for better performance.
0568     //
0569     //      Set the value BOOST_KARMA_NUMERICS_LOOP_UNROLL to some integer in
0570     //      between 0 (no unrolling) and the largest expected generated integer
0571     //      string length (complete unrolling).
0572     //      If not specified, this value defaults to 6.
0573     //
0574     ///////////////////////////////////////////////////////////////////////////
0575 #define BOOST_KARMA_NUMERICS_INNER_LOOP_PREFIX(z, x, data)                    \
0576         if (!traits::test_zero(n)) {                                          \
0577             int ch_##x = radix_type::call(remainder_type::call(n));           \
0578             n = divide_type::call(n, num, ++exp);                             \
0579     /**/
0580 
0581 #define BOOST_KARMA_NUMERICS_INNER_LOOP_SUFFIX(z, x, n_rolls_sub1)            \
0582             *sink = char(BOOST_PP_CAT(ch_, BOOST_PP_SUB(n_rolls_sub1, x)));   \
0583             ++sink;                                                           \
0584         }                                                                     \
0585     /**/
0586 
0587     template <
0588         unsigned Radix, typename CharEncoding = unused_type
0589       , typename Tag = unused_type>
0590     struct int_inserter
0591     {
0592         typedef traits::convert_digit<Radix, CharEncoding, Tag> radix_type;
0593         typedef traits::divide<Radix> divide_type;
0594         typedef traits::remainder<Radix> remainder_type;
0595 
0596         template <typename OutputIterator, typename T>
0597         static bool
0598         call(OutputIterator& sink, T n, T& num, int exp)
0599         {
0600             // remainder_type::call returns n % Radix
0601             int ch = radix_type::call(remainder_type::call(n));
0602             n = divide_type::call(n, num, ++exp);
0603 
0604             BOOST_PP_REPEAT(
0605                 BOOST_KARMA_NUMERICS_LOOP_UNROLL,
0606                 BOOST_KARMA_NUMERICS_INNER_LOOP_PREFIX, _);
0607 
0608             if (!traits::test_zero(n))
0609                 call(sink, n, num, exp);
0610 
0611             BOOST_PP_REPEAT(
0612                 BOOST_KARMA_NUMERICS_LOOP_UNROLL,
0613                 BOOST_KARMA_NUMERICS_INNER_LOOP_SUFFIX,
0614                 BOOST_PP_DEC(BOOST_KARMA_NUMERICS_LOOP_UNROLL));
0615 
0616             *sink = char(ch);
0617             ++sink;
0618             return true;
0619         }
0620 
0621         //  Common code for integer string representations
0622         template <typename OutputIterator, typename T>
0623         static bool
0624         call(OutputIterator& sink, T n)
0625         {
0626             return call(sink, n, n, 0);
0627         }
0628 
0629     private:
0630         // helper function returning the biggest number representable either in
0631         // a boost::long_long_type (if this does exist) or in a plain long
0632         // otherwise
0633 #if defined(BOOST_HAS_LONG_LONG)
0634         typedef boost::long_long_type biggest_long_type;
0635 #else
0636         typedef long biggest_long_type;
0637 #endif
0638 
0639         static biggest_long_type max_long()
0640         {
0641             return (std::numeric_limits<biggest_long_type>::max)();
0642         }
0643 
0644     public:
0645         // Specialization for doubles and floats, falling back to long integers
0646         // for representable values. These specializations speed up formatting
0647         // of floating point numbers considerably as all the required
0648         // arithmetics will be executed using integral data types.
0649         template <typename OutputIterator>
0650         static bool
0651         call(OutputIterator& sink, long double n)
0652         {
0653             if (std::fabs(n) < max_long())
0654             {
0655                 biggest_long_type l((biggest_long_type)n);
0656                 return call(sink, l, l, 0);
0657             }
0658             return call(sink, n, n, 0);
0659         }
0660         template <typename OutputIterator>
0661         static bool
0662         call(OutputIterator& sink, double n)
0663         {
0664             if (std::fabs(n) < max_long())
0665             {
0666                 biggest_long_type l((biggest_long_type)n);
0667                 return call(sink, l, l, 0);
0668             }
0669             return call(sink, n, n, 0);
0670         }
0671         template <typename OutputIterator>
0672         static bool
0673         call(OutputIterator& sink, float n)
0674         {
0675             if (std::fabs(n) < max_long())
0676             {
0677                 biggest_long_type l((biggest_long_type)n);
0678                 return call(sink, l, l, 0);
0679             }
0680             return call(sink, n, n, 0);
0681         }
0682     };
0683 
0684 #undef BOOST_KARMA_NUMERICS_INNER_LOOP_PREFIX
0685 #undef BOOST_KARMA_NUMERICS_INNER_LOOP_SUFFIX
0686 
0687     ///////////////////////////////////////////////////////////////////////////
0688     //
0689     //  The uint_inserter template takes care of the conversion of any integer
0690     //  to a string, while interpreting the number as an unsigned type.
0691     //
0692     ///////////////////////////////////////////////////////////////////////////
0693     template <
0694         unsigned Radix, typename CharEncoding = unused_type
0695       , typename Tag = unused_type>
0696     struct uint_inserter : int_inserter<Radix, CharEncoding, Tag>
0697     {
0698         typedef int_inserter<Radix, CharEncoding, Tag> base_type;
0699 
0700         //  Common code for integer string representations
0701         template <typename OutputIterator, typename T>
0702         static bool
0703         call(OutputIterator& sink, T const& n)
0704         {
0705             typedef typename traits::absolute_value<T>::type type;
0706             type un = type(n);
0707             return base_type::call(sink, un, un, 0);
0708         }
0709     };
0710 
0711     ///////////////////////////////////////////////////////////////////////////
0712     //
0713     //  The sign_inserter template generates a sign for a given numeric value.
0714     //
0715     //    The parameter forcesign allows to generate a sign even for positive
0716     //    numbers.
0717     //
0718     ///////////////////////////////////////////////////////////////////////////
0719     struct sign_inserter
0720     {
0721         template <typename OutputIterator>
0722         static bool
0723         call_noforce(OutputIterator& sink, bool is_zero, bool is_negative,
0724             bool sign_if_zero)
0725         {
0726             // generate a sign for negative numbers only
0727             if (is_negative || (is_zero && sign_if_zero)) {
0728                 *sink = '-';
0729                 ++sink;
0730             }
0731             return true;
0732         }
0733 
0734         template <typename OutputIterator>
0735         static bool
0736         call_force(OutputIterator& sink, bool is_zero, bool is_negative,
0737             bool sign_if_zero)
0738         {
0739             // generate a sign for all numbers except zero
0740             if (!is_zero || sign_if_zero)
0741                 *sink = is_negative ? '-' : '+';
0742             else
0743                 *sink = ' ';
0744 
0745             ++sink;
0746             return true;
0747         }
0748 
0749         template <typename OutputIterator>
0750         static bool
0751         call(OutputIterator& sink, bool is_zero, bool is_negative
0752           , bool forcesign, bool sign_if_zero = false)
0753         {
0754             return forcesign ?
0755                 call_force(sink, is_zero, is_negative, sign_if_zero) :
0756                 call_noforce(sink, is_zero, is_negative, sign_if_zero);
0757         }
0758     };
0759 
0760     ///////////////////////////////////////////////////////////////////////////
0761     //  These are helper functions for the real policies allowing to generate
0762     //  a single character and a string
0763     ///////////////////////////////////////////////////////////////////////////
0764     template <typename CharEncoding = unused_type, typename Tag = unused_type>
0765     struct char_inserter
0766     {
0767         template <typename OutputIterator, typename Char>
0768         static bool call(OutputIterator& sink, Char c)
0769         {
0770             return detail::generate_to(sink, c, CharEncoding(), Tag());
0771         }
0772     };
0773 
0774     template <typename CharEncoding = unused_type, typename Tag = unused_type>
0775     struct string_inserter
0776     {
0777         template <typename OutputIterator, typename String>
0778         static bool call(OutputIterator& sink, String str)
0779         {
0780             return detail::string_generate(sink, str, CharEncoding(), Tag());
0781         }
0782     };
0783 
0784 }}}
0785 
0786 #endif