1 
2 #ifndef BOOST_MPL_STRING_HPP_INCLUDED
3 #define BOOST_MPL_STRING_HPP_INCLUDED
4 
5 // Copyright Eric Niebler 2009
6 //
7 // Distributed under the Boost Software License, Version 1.0.
8 // (See accompanying file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10 //
11 // See http://www.boost.org/libs/mpl for documentation.
12 
13 // $Id: string.hpp 49239 2009-04-01 09:10:26Z eric_niebler $
14 // $Date: 2009-04-01 02:10:26 -0700 (Wed, 1 Apr 2009) $
15 // $Revision: 49239 $
16 //
17 // Thanks to:
18 //   Dmitry Goncharov for porting this to the Sun compiler
19 
20 #include <boost/config.hpp>
21 #include <boost/detail/workaround.hpp>
22 #include <boost/predef/other/endian.h>
23 #include <boost/mpl/limits/string.hpp>
24 #include <boost/mpl/if.hpp>
25 #include <boost/mpl/char.hpp>
26 #include <boost/mpl/copy.hpp>
27 #include <boost/mpl/size.hpp>
28 #include <boost/mpl/empty.hpp>
29 #include <boost/mpl/assert.hpp>
30 #include <boost/mpl/size_t.hpp>
31 #include <boost/mpl/begin_end.hpp>
32 #include <boost/mpl/joint_view.hpp>
33 #include <boost/mpl/insert_range.hpp>
34 #include <boost/mpl/back_inserter.hpp>
35 #include <boost/mpl/front_inserter.hpp>
36 #include <boost/mpl/iterator_range.hpp>
37 #include <boost/preprocessor/arithmetic/dec.hpp>
38 #include <boost/preprocessor/arithmetic/add.hpp>
39 #include <boost/preprocessor/arithmetic/div.hpp>
40 #include <boost/preprocessor/punctuation/comma_if.hpp>
41 #include <boost/preprocessor/repetition/repeat.hpp>
42 #include <boost/preprocessor/repetition/enum_params.hpp>
43 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
44 #include <boost/preprocessor/repetition/enum_shifted_params.hpp>
45 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
46 #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
47 
48 #include <iterator> // for bidirectional_iterator_tag
49 #include <climits>
50 
51 namespace boost { namespace mpl
52 {
53     #define BOOST_MPL_STRING_MAX_PARAMS                                                             \
54       BOOST_PP_DIV(BOOST_PP_ADD(BOOST_MPL_LIMIT_STRING_SIZE, 3), 4)
55 
56     // Low-level bit-twiddling is done by macros. Any implementation-defined behavior of
57     // multi-character literals should be localized to these macros.
58 
59     #define BOOST_MPL_MULTICHAR_LENGTH(c)                                                           \
60       (std::size_t)((c<CHAR_MIN) ? 4 : ((c>0xffffff)+(c>0xffff)+(c>0xff)+1))
61 
62     #if BOOST_ENDIAN_LITTLE_BYTE && defined(__SUNPRO_CC)
63 
64         #define BOOST_MPL_MULTICHAR_AT(c,i)                                                         \
65           (char)(0xff&((unsigned)(c)>>(8*(std::size_t)(i))))
66 
67         #define BOOST_MPL_MULTICHAR_PUSH_BACK(c,i)                                                  \
68           ((((unsigned char)(i))<<(BOOST_MPL_MULTICHAR_LENGTH(c)*8))|(unsigned)(c))
69 
70         #define BOOST_MPL_MULTICHAR_PUSH_FRONT(c,i)                                                 \
71           (((unsigned)(c)<<8)|(unsigned char)(i))
72 
73         #define BOOST_MPL_MULTICHAR_POP_BACK(c)                                                     \
74           (((1<<((BOOST_MPL_MULTICHAR_LENGTH(c)-1)*8))-1)&(unsigned)(c))
75 
76         #define BOOST_MPL_MULTICHAR_POP_FRONT(c)                                                    \
77           ((unsigned)(c)>>8)
78 
79     #else
80 
81         #define BOOST_MPL_MULTICHAR_AT(c,i)                                                         \
82           (char)(0xff&((unsigned)(c)>>(8*(BOOST_MPL_MULTICHAR_LENGTH(c)-(std::size_t)(i)-1))))
83 
84         #define BOOST_MPL_MULTICHAR_PUSH_BACK(c,i)                                                  \
85           (((unsigned)(c)<<8)|(unsigned char)(i))
86 
87         #define BOOST_MPL_MULTICHAR_PUSH_FRONT(c,i)                                                 \
88           ((((unsigned char)(i))<<(BOOST_MPL_MULTICHAR_LENGTH(c)*8))|(unsigned)(c))
89 
90         #define BOOST_MPL_MULTICHAR_POP_BACK(c)                                                     \
91           ((unsigned)(c)>>8)
92 
93         #define BOOST_MPL_MULTICHAR_POP_FRONT(c)                                                    \
94           (((1<<((BOOST_MPL_MULTICHAR_LENGTH(c)-1)*8))-1)&(unsigned)(c))
95 
96     #endif
97 
98     struct string_tag;
99     struct string_iterator_tag;
100 
101     template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_MPL_STRING_MAX_PARAMS, int C, 0)>
102     struct string;
103 
104     template<typename Sequence, int I, int J>
105     struct string_iterator;
106 
107     template<typename Sequence>
108     struct sequence_tag;
109 
110     template<typename Tag>
111     struct size_impl;
112 
113     template<>
114     struct size_impl<mpl::string_tag>
115     {
116         template<typename Sequence>
117         struct apply;
118 
119         #define M0(z, n, data)                                                                      \
120         + BOOST_MPL_MULTICHAR_LENGTH(BOOST_PP_CAT(C,n))
121 
122         #define M1(z, n, data)                                                                      \
123         template<BOOST_PP_ENUM_PARAMS_Z(z, n, int C)>                                               \
124         struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)> >                                 \
125           : mpl::size_t<(0 BOOST_PP_REPEAT_ ## z(n, M0, ~))>                                        \
126         {};
127 
128         BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_MPL_STRING_MAX_PARAMS), M1, ~)
129         #undef M0
130         #undef M1
131     };
132 
133     template<>
134     struct size_impl<mpl::string_tag>::apply<mpl::string<> >
135       : mpl::size_t<0>
136     {};
137 
138     template<typename Tag>
139     struct begin_impl;
140 
141     template<>
142     struct begin_impl<mpl::string_tag>
143     {
144         template<typename Sequence>
145         struct apply
146         {
147             typedef mpl::string_iterator<Sequence, 0, 0> type;
148         };
149     };
150 
151     template<typename Tag>
152     struct end_impl;
153 
154     template<>
155     struct end_impl<mpl::string_tag>
156     {
157         template<typename Sequence>
158         struct apply;
159 
160         #define M0(z,n,data)                                                                        \
161         template<BOOST_PP_ENUM_PARAMS_Z(z, n, int C)>                                               \
162         struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)> >                                 \
163         {                                                                                           \
164             typedef mpl::string_iterator<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)>, n, 0> type;  \
165         };
166 
167         BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_MPL_STRING_MAX_PARAMS), M0, ~)
168         #undef M0
169     };
170 
171     template<>
172     struct end_impl<mpl::string_tag>::apply<mpl::string<> >
173     {
174         typedef mpl::string_iterator<mpl::string<>, 0, 0> type;
175     };
176 
177     template<typename Tag>
178     struct push_back_impl;
179 
180     template<>
181     struct push_back_impl<mpl::string_tag>
182     {
183         template<typename Sequence, typename Value, bool B = (4==BOOST_MPL_MULTICHAR_LENGTH(Sequence::back_))>
184         struct apply
185         {
186             BOOST_MPL_ASSERT_MSG(
187                 (BOOST_MPL_LIMIT_STRING_SIZE != mpl::size<Sequence>::type::value)
188               , PUSH_BACK_FAILED_MPL_STRING_IS_FULL
189               , (Sequence)
190             );
191             // If the above assertion didn't fire, then the string is sparse.
192             // Repack the string and retry the push_back
193             typedef
194                 typename mpl::push_back<
195                     typename mpl::copy<
196                         Sequence
197                       , mpl::back_inserter<mpl::string<> >
198                     >::type
199                   , Value
200                 >::type
201             type;
202         };
203 
204         template<typename Value>
205         struct apply<mpl::string<>, Value, false>
206         {
207             typedef mpl::string<(char)Value::value> type;
208         };
209 
210         #define M0(z,n,data)                                                                        \
211         template<BOOST_PP_ENUM_PARAMS_Z(z, n, int C), typename Value>                               \
212         struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)>, Value, false>                    \
213         {                                                                                           \
214             typedef                                                                                 \
215                 mpl::string<                                                                        \
216                     BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_DEC(n), C)                                   \
217                     BOOST_PP_COMMA_IF(BOOST_PP_DEC(n))                                              \
218                     ((unsigned)BOOST_PP_CAT(C,BOOST_PP_DEC(n))>0xffffff)                            \
219                     ?BOOST_PP_CAT(C,BOOST_PP_DEC(n))                                                \
220                     :BOOST_MPL_MULTICHAR_PUSH_BACK(BOOST_PP_CAT(C,BOOST_PP_DEC(n)), Value::value)   \
221                   , ((unsigned)BOOST_PP_CAT(C,BOOST_PP_DEC(n))>0xffffff)                            \
222                     ?(char)Value::value                                                             \
223                     :0                                                                              \
224                 >                                                                                   \
225             type;                                                                                   \
226         };
227 
228         BOOST_PP_REPEAT_FROM_TO(1, BOOST_MPL_STRING_MAX_PARAMS, M0, ~)
229         #undef M0
230 
231         template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, int C), typename Value>
232         struct apply<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, Value, false>
233         {
234             typedef
235                 mpl::string<
236                     BOOST_PP_ENUM_PARAMS(BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS), C)
237                   , BOOST_MPL_MULTICHAR_PUSH_BACK(BOOST_PP_CAT(C,BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS)), Value::value)
238                 >
239             type;
240         };
241     };
242 
243     template<typename Tag>
244     struct has_push_back_impl;
245 
246     template<>
247     struct has_push_back_impl<mpl::string_tag>
248     {
249         template<typename Sequence>
250         struct apply
251           : mpl::true_
252         {};
253     };
254 
255     template<typename Tag>
256     struct pop_back_impl;
257 
258     template<>
259     struct pop_back_impl<mpl::string_tag>
260     {
261         template<typename Sequence>
262         struct apply;
263 
264         #define M0(z,n,data)                                                                        \
265         template<BOOST_PP_ENUM_PARAMS_Z(z, n, int C)>                                               \
266         struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)> >                                 \
267         {                                                                                           \
268             BOOST_MPL_ASSERT_MSG((C0 != 0), POP_BACK_FAILED_MPL_STRING_IS_EMPTY, (mpl::string<>));  \
269             typedef                                                                                 \
270                 mpl::string<                                                                        \
271                     BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_DEC(n), C)                                   \
272                     BOOST_PP_COMMA_IF(BOOST_PP_DEC(n))                                              \
273                     BOOST_MPL_MULTICHAR_POP_BACK(BOOST_PP_CAT(C,BOOST_PP_DEC(n)))                   \
274                 >                                                                                   \
275             type;                                                                                   \
276         };
277 
278         BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_MPL_STRING_MAX_PARAMS), M0, ~)
279         #undef M0
280     };
281 
282     template<typename Tag>
283     struct has_pop_back_impl;
284 
285     template<>
286     struct has_pop_back_impl<mpl::string_tag>
287     {
288         template<typename Sequence>
289         struct apply
290           : mpl::true_
291         {};
292     };
293 
294     template<typename Tag>
295     struct push_front_impl;
296 
297     template<>
298     struct push_front_impl<mpl::string_tag>
299     {
300         template<typename Sequence, typename Value, bool B = (4==BOOST_MPL_MULTICHAR_LENGTH(Sequence::front_))>
301         struct apply
302         {
303             BOOST_MPL_ASSERT_MSG(
304                 (BOOST_MPL_LIMIT_STRING_SIZE != mpl::size<Sequence>::type::value)
305               , PUSH_FRONT_FAILED_MPL_STRING_IS_FULL
306               , (Sequence)
307             );
308             // If the above assertion didn't fire, then the string is sparse.
309             // Repack the string and retry the push_front.
310             typedef
311                 typename mpl::push_front<
312                     typename mpl::reverse_copy<
313                         Sequence
314                       , mpl::front_inserter<string<> >
315                     >::type
316                   , Value
317                 >::type
318             type;
319         };
320 
321         #if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
322         template<typename Value>
323         struct apply<mpl::string<>, Value, false>
324         {
325             typedef mpl::string<(char)Value::value> type;
326         };
327         #endif
328 
329         #define M0(z,n,data)                                                                        \
330         template<BOOST_PP_ENUM_PARAMS_Z(z, n, int C), typename Value>                               \
331         struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)>, Value, true>                     \
332         {                                                                                           \
333             typedef                                                                                 \
334                 mpl::string<                                                                        \
335                     (char)Value::value                                                              \
336                     BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, C)                                        \
337                 >                                                                                   \
338             type;                                                                                   \
339         };
340 
341         BOOST_PP_REPEAT_FROM_TO(1, BOOST_MPL_STRING_MAX_PARAMS, M0, ~)
342         #undef M0
343 
344         template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, int C), typename Value>
345         struct apply<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, Value, false>
346         {
347             typedef
348                 mpl::string<
349                     BOOST_MPL_MULTICHAR_PUSH_FRONT(C0, Value::value)
350                   , BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)
351                 >
352             type0;
353 
354             #if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
355             typedef
356                 typename mpl::if_<
357                     mpl::empty<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)> >
358                   , mpl::string<(char)Value::value>
359                   , type0
360                 >::type
361             type;
362             #else
363             typedef type0 type;
364             #endif
365         };
366     };
367 
368     template<typename Tag>
369     struct has_push_front_impl;
370 
371     template<>
372     struct has_push_front_impl<mpl::string_tag>
373     {
374         template<typename Sequence>
375         struct apply
376           : mpl::true_
377         {};
378     };
379 
380     template<typename Tag>
381     struct pop_front_impl;
382 
383     template<>
384     struct pop_front_impl<mpl::string_tag>
385     {
386         template<typename Sequence, bool B = (1==BOOST_MPL_MULTICHAR_LENGTH(Sequence::front_))>
387         struct apply;
388 
389         #define M0(z,n,data)                                                                        \
390         template<BOOST_PP_ENUM_PARAMS_Z(z, n, int C)>                                               \
391         struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)>, true>                            \
392         {                                                                                           \
393             BOOST_MPL_ASSERT_MSG((C0 != 0), POP_FRONT_FAILED_MPL_STRING_IS_EMPTY, (mpl::string<>)); \
394             typedef                                                                                 \
395                 mpl::string<BOOST_PP_ENUM_SHIFTED_PARAMS_Z(z, n, C)>                                \
396             type;                                                                                   \
397         };
398 
399         BOOST_PP_REPEAT_FROM_TO(1, BOOST_MPL_STRING_MAX_PARAMS, M0, ~)
400         #undef M0
401 
402         template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, int C)>
403         struct apply<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, false>
404         {
405             typedef
406                 mpl::string<
407                     BOOST_MPL_MULTICHAR_POP_FRONT(C0)
408                   , BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)
409                 >
410             type;
411         };
412     };
413 
414     template<typename Tag>
415     struct has_pop_front_impl;
416 
417     template<>
418     struct has_pop_front_impl<mpl::string_tag>
419     {
420         template<typename Sequence>
421         struct apply
422           : mpl::true_
423         {};
424     };
425 
426     template<typename Tag>
427     struct insert_range_impl;
428 
429     template<>
430     struct insert_range_impl<mpl::string_tag>
431     {
432         template<typename Sequence, typename Pos, typename Range>
433         struct apply
434           : mpl::copy<
435                 mpl::joint_view<
436                     mpl::iterator_range<
437                         mpl::string_iterator<Sequence, 0, 0>
438                       , Pos
439                     >
440                   , mpl::joint_view<
441                         Range
442                       , mpl::iterator_range<
443                             Pos
444                           , typename mpl::end<Sequence>::type
445                         >
446                     >
447                 >
448               , mpl::back_inserter<mpl::string<> >
449             >
450         {};
451     };
452 
453     template<typename Tag>
454     struct insert_impl;
455 
456     template<>
457     struct insert_impl<mpl::string_tag>
458     {
459         template<typename Sequence, typename Pos, typename Value>
460         struct apply
461           : mpl::insert_range<Sequence, Pos, mpl::string<(char)Value::value> >
462         {};
463     };
464 
465     template<typename Tag>
466     struct erase_impl;
467 
468     template<>
469     struct erase_impl<mpl::string_tag>
470     {
471         template<typename Sequence, typename First, typename Last>
472         struct apply
473           : mpl::copy<
474                 mpl::joint_view<
475                     mpl::iterator_range<
476                         mpl::string_iterator<Sequence, 0, 0>
477                       , First
478                     >
479                   , mpl::iterator_range<
480                         typename mpl::if_na<Last, typename mpl::next<First>::type>::type
481                       , typename mpl::end<Sequence>::type
482                     >
483                 >
484               , mpl::back_inserter<mpl::string<> >
485             >
486         {};
487     };
488 
489     template<typename Tag>
490     struct clear_impl;
491 
492     template<>
493     struct clear_impl<mpl::string_tag>
494     {
495         template<typename>
496         struct apply
497         {
498             typedef mpl::string<> type;
499         };
500     };
501 
502     #define M0(z, n, data)                                                                            \
503     template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, int C), int J>                         \
504     struct string_iterator<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, n, J>   \
505     {                                                                                                 \
506         enum { eomc_ = (BOOST_MPL_MULTICHAR_LENGTH(BOOST_PP_CAT(C, n)) == J + 1) };                   \
507         typedef mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)> string;             \
508         typedef std::bidirectional_iterator_tag category;                                             \
509         typedef                                                                                       \
510             mpl::string_iterator<string, n + eomc_, eomc_ ? 0 : J + 1>                                \
511         next;                                                                                         \
512         typedef                                                                                       \
513             mpl::string_iterator<string, n, J - 1>                                                    \
514         prior;                                                                                        \
515         typedef mpl::char_<BOOST_MPL_MULTICHAR_AT(BOOST_PP_CAT(C, n), J)> type;                       \
516     };                                                                                                \
517     template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, int C)>                                \
518     struct string_iterator<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, n, 0>   \
519     {                                                                                                 \
520         enum { eomc_ = (BOOST_MPL_MULTICHAR_LENGTH(BOOST_PP_CAT(C, n)) == 1) };                       \
521         typedef mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)> string;             \
522         typedef std::bidirectional_iterator_tag category;                                             \
523         typedef                                                                                       \
524             mpl::string_iterator<string, n + eomc_, !eomc_>                                           \
525         next;                                                                                         \
526         typedef                                                                                       \
527             mpl::string_iterator<                                                                     \
528                 string                                                                                \
529               , n - 1                                                                                 \
530               , BOOST_MPL_MULTICHAR_LENGTH(BOOST_PP_CAT(C, BOOST_PP_DEC(n))) - 1                      \
531             >                                                                                         \
532         prior;                                                                                        \
533         typedef mpl::char_<BOOST_MPL_MULTICHAR_AT(BOOST_PP_CAT(C, n), 0)> type;                       \
534     };
535 
536     BOOST_PP_REPEAT(BOOST_MPL_STRING_MAX_PARAMS, M0, ~)
537     #undef M0
538 
539     template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, int C)>
540     struct string
541     {
542         /// INTERNAL ONLY
543         enum
544         {
545             front_  = C0
546           , back_   = BOOST_PP_CAT(C, BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS))
547         };
548 
549         typedef char        value_type;
550         typedef string      type;
551         typedef string_tag  tag;
552     };
553 
554     namespace aux_
555     {
556         template<typename It, typename End>
557         struct next_unless
558           : mpl::next<It>
559         {};
560 
561         template<typename End>
562         struct next_unless<End, End>
563         {
564             typedef End type;
565         };
566 
567         template<typename It, typename End>
568         struct deref_unless
569           : mpl::deref<It>
570         {};
571 
572         template<typename End>
573         struct deref_unless<End, End>
574         {
575             typedef mpl::char_<'\0'> type;
576         };
577     }
578 
579     template<typename Sequence>
580     struct c_str
581     {
582         typedef typename mpl::end<Sequence>::type iend;
583         typedef typename mpl::begin<Sequence>::type i0;
584         #define M0(z, n, data)                                                                      \
585         typedef                                                                                     \
586             typename mpl::aux_::next_unless<BOOST_PP_CAT(i, n), iend>::type                         \
587         BOOST_PP_CAT(i, BOOST_PP_INC(n));
588         BOOST_PP_REPEAT(BOOST_MPL_LIMIT_STRING_SIZE, M0, ~)
589         #undef M0
590 
591         typedef c_str type;
592         static typename Sequence::value_type const value[BOOST_MPL_LIMIT_STRING_SIZE+1];
593     };
594 
595     template<typename Sequence>
596     typename Sequence::value_type const c_str<Sequence>::value[BOOST_MPL_LIMIT_STRING_SIZE+1] =
597     {
598         #define M0(z, n, data)                                                                      \
599         mpl::aux_::deref_unless<BOOST_PP_CAT(i, n), iend>::type::value,
600         BOOST_PP_REPEAT(BOOST_MPL_LIMIT_STRING_SIZE, M0, ~)
601         #undef M0
602         '\0'
603     };
604 
605 }} // namespace boost
606 
607 #endif // BOOST_MPL_STRING_HPP_INCLUDED
608