1 
2 // Copyright Eric Niebler 2009
3 //
4 // Distributed under the Boost Software License, Version 1.0.
5 // (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // See http://www.boost.org/libs/mpl for documentation.
9 
10 // $Id: string.cpp 49240 2009-04-01 09:21:07Z eric_niebler $
11 // $Date: 2009-04-01 02:21:07 -0700 (Wed, 1 Apr 2009) $
12 // $Revision: 49240 $
13 
14 #include <string>
15 #include <cstring>
16 #include <iostream>
17 
18 #include <boost/mpl/string.hpp>
19 
20 #include <boost/mpl/at.hpp>
21 #include <boost/mpl/back.hpp>
22 #include <boost/mpl/empty.hpp>
23 #include <boost/mpl/front.hpp>
24 #include <boost/mpl/erase.hpp>
25 #include <boost/mpl/insert.hpp>
26 #include <boost/mpl/advance.hpp>
27 #include <boost/mpl/for_each.hpp>
28 #include <boost/mpl/vector_c.hpp>
29 #include <boost/mpl/pop_back.hpp>
30 #include <boost/mpl/pop_front.hpp>
31 #include <boost/mpl/push_back.hpp>
32 #include <boost/mpl/push_front.hpp>
33 #include <boost/type_traits/is_same.hpp>
34 #include <boost/detail/lightweight_test.hpp>
35 
36 namespace mpl = boost::mpl;
37 
38 // Accept a string as a template parameter!
39 template<char const *sz>
40 struct greeting
41 {
say_hellogreeting42     std::string say_hello() const
43     {
44         return sz;
45     }
46 };
47 
48 struct push_char
49 {
push_charpush_char50     push_char(std::string &str)
51       : str_(&str)
52     {}
53 
operator ()push_char54     void operator()(char ch) const
55     {
56         this->str_->push_back(ch);
57     }
58 
59     std::string *str_;
60 };
61 
main()62 int main()
63 {
64     // Test mpl::size of strings
65     {
66         typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaa'> almost_full;
67         typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'> full;
68 
69         BOOST_MPL_ASSERT_RELATION(0,  ==, (mpl::size<mpl::string<> >::value));
70         BOOST_MPL_ASSERT_RELATION(1,  ==, (mpl::size<mpl::string<'a'> >::value));
71         BOOST_MPL_ASSERT_RELATION(2,  ==, (mpl::size<mpl::string<'ab'> >::value));
72         BOOST_MPL_ASSERT_RELATION(2,  ==, (mpl::size<mpl::string<'a','b'> >::value));
73         BOOST_MPL_ASSERT_RELATION(4,  ==, (mpl::size<mpl::string<'abcd'> >::value));
74         BOOST_MPL_ASSERT_RELATION(5,  ==, (mpl::size<mpl::string<'abcd','e'> >::value));
75         BOOST_MPL_ASSERT_RELATION(31, ==, (mpl::size<almost_full>::value));
76         BOOST_MPL_ASSERT_RELATION(32, ==, (mpl::size<full>::value));
77     }
78 
79     // Test mpl::begin and mpl::end with strings
80     {
81         typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaa'> almost_full;
82         typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'> full;
83 
84         BOOST_MPL_ASSERT((
85             boost::is_same<
86                 mpl::begin<mpl::string<> >::type
87               , mpl::end<mpl::string<> >::type
88             >
89         ));
90 
91         BOOST_MPL_ASSERT((
92             boost::is_same<
93                 mpl::begin<mpl::string<'a'> >::type
94               , mpl::string_iterator<mpl::string<'a'>, 0, 0>
95             >
96         ));
97 
98         BOOST_MPL_ASSERT((
99             boost::is_same<
100                 mpl::end<mpl::string<'a'> >::type
101               , mpl::string_iterator<mpl::string<'a'>, 1, 0>
102             >
103         ));
104 
105         BOOST_MPL_ASSERT((
106             boost::is_same<
107                 mpl::begin<almost_full>::type
108               , mpl::string_iterator<almost_full, 0, 0>
109             >
110         ));
111 
112         BOOST_MPL_ASSERT((
113             boost::is_same<
114                 mpl::end<almost_full>::type
115               , mpl::string_iterator<almost_full, 8, 0>
116             >
117         ));
118 
119         BOOST_MPL_ASSERT((
120             boost::is_same<
121                 mpl::begin<full>::type
122               , mpl::string_iterator<full, 0, 0>
123             >
124         ));
125 
126         BOOST_MPL_ASSERT((
127             boost::is_same<
128                 mpl::end<full>::type
129               , mpl::string_iterator<full, 8, 0>
130             >
131         ));
132     }
133 
134     // testing push_back
135     {
136         typedef mpl::push_back<mpl::string<>, mpl::char_<'a'> >::type t1;
137         BOOST_MPL_ASSERT((boost::is_same<t1, mpl::string<'a'> >));
138 
139         typedef mpl::push_back<t1, mpl::char_<'b'> >::type t2;
140         BOOST_MPL_ASSERT((boost::is_same<t2, mpl::string<'ab'> >));
141 
142         typedef mpl::push_back<t2, mpl::char_<'c'> >::type t3;
143         BOOST_MPL_ASSERT((boost::is_same<t3, mpl::string<'abc'> >));
144 
145         typedef mpl::push_back<t3, mpl::char_<'d'> >::type t4;
146         BOOST_MPL_ASSERT((boost::is_same<t4, mpl::string<'abcd'> >));
147 
148         typedef mpl::push_back<t4, mpl::char_<'e'> >::type t5;
149         BOOST_MPL_ASSERT((boost::is_same<t5, mpl::string<'abcd','e'> >));
150 
151         typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaa'> almost_full;
152         typedef mpl::push_back<almost_full, mpl::char_<'X'> >::type t6;
153         BOOST_MPL_ASSERT((boost::is_same<t6, mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaX'> >));
154     }
155 
156     // Test mpl::next
157     {
158         typedef mpl::string<'a','bc','def','ghij'> s;
159 
160         typedef mpl::begin<s>::type i0;
161         BOOST_MPL_ASSERT((boost::is_same<i0, mpl::string_iterator<s,0,0> >));
162 
163         typedef mpl::next<i0>::type i1;
164         BOOST_MPL_ASSERT((boost::is_same<i1, mpl::string_iterator<s,1,0> >));
165 
166         typedef mpl::next<i1>::type i2;
167         BOOST_MPL_ASSERT((boost::is_same<i2, mpl::string_iterator<s,1,1> >));
168 
169         typedef mpl::next<i2>::type i3;
170         BOOST_MPL_ASSERT((boost::is_same<i3, mpl::string_iterator<s,2,0> >));
171 
172         typedef mpl::next<i3>::type i4;
173         BOOST_MPL_ASSERT((boost::is_same<i4, mpl::string_iterator<s,2,1> >));
174 
175         typedef mpl::next<i4>::type i5;
176         BOOST_MPL_ASSERT((boost::is_same<i5, mpl::string_iterator<s,2,2> >));
177 
178         typedef mpl::next<i5>::type i6;
179         BOOST_MPL_ASSERT((boost::is_same<i6, mpl::string_iterator<s,3,0> >));
180 
181         typedef mpl::next<i6>::type i7;
182         BOOST_MPL_ASSERT((boost::is_same<i7, mpl::string_iterator<s,3,1> >));
183 
184         typedef mpl::next<i7>::type i8;
185         BOOST_MPL_ASSERT((boost::is_same<i8, mpl::string_iterator<s,3,2> >));
186 
187         typedef mpl::next<i8>::type i9;
188         BOOST_MPL_ASSERT((boost::is_same<i9, mpl::string_iterator<s,3,3> >));
189 
190         typedef mpl::next<i9>::type i10;
191         BOOST_MPL_ASSERT((boost::is_same<i10, mpl::string_iterator<s,4,0> >));
192 
193         BOOST_MPL_ASSERT((boost::is_same<i10, mpl::end<s>::type>));
194     }
195 
196     // Test mpl::prior
197     {
198         typedef mpl::string<'a','bc','def','ghij'> s;
199 
200         typedef mpl::end<s>::type i10;
201         BOOST_MPL_ASSERT((boost::is_same<i10, mpl::string_iterator<s,4,0> >));
202 
203         typedef mpl::prior<i10>::type i9;
204         BOOST_MPL_ASSERT((boost::is_same<i9, mpl::string_iterator<s,3,3> >));
205 
206         typedef mpl::prior<i9>::type i8;
207         BOOST_MPL_ASSERT((boost::is_same<i8, mpl::string_iterator<s,3,2> >));
208 
209         typedef mpl::prior<i8>::type i7;
210         BOOST_MPL_ASSERT((boost::is_same<i7, mpl::string_iterator<s,3,1> >));
211 
212         typedef mpl::prior<i7>::type i6;
213         BOOST_MPL_ASSERT((boost::is_same<i6, mpl::string_iterator<s,3,0> >));
214 
215         typedef mpl::prior<i6>::type i5;
216         BOOST_MPL_ASSERT((boost::is_same<i5, mpl::string_iterator<s,2,2> >));
217 
218         typedef mpl::prior<i5>::type i4;
219         BOOST_MPL_ASSERT((boost::is_same<i4, mpl::string_iterator<s,2,1> >));
220 
221         typedef mpl::prior<i4>::type i3;
222         BOOST_MPL_ASSERT((boost::is_same<i3, mpl::string_iterator<s,2,0> >));
223 
224         typedef mpl::prior<i3>::type i2;
225         BOOST_MPL_ASSERT((boost::is_same<i2, mpl::string_iterator<s,1,1> >));
226 
227         typedef mpl::prior<i2>::type i1;
228         BOOST_MPL_ASSERT((boost::is_same<i1, mpl::string_iterator<s,1,0> >));
229 
230         typedef mpl::prior<i1>::type i0;
231         BOOST_MPL_ASSERT((boost::is_same<i0, mpl::string_iterator<s,0,0> >));
232 
233         BOOST_MPL_ASSERT((boost::is_same<i0, mpl::begin<s>::type>));
234     }
235 
236     // Test mpl::deref
237     {
238         typedef mpl::string<'a','bc','def','ghij'> s;
239 
240         typedef mpl::begin<s>::type i0;
241         BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i0>::type, mpl::char_<'a'> >));
242 
243         typedef mpl::next<i0>::type i1;
244         BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i1>::type, mpl::char_<'b'> >));
245 
246         typedef mpl::next<i1>::type i2;
247         BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i2>::type, mpl::char_<'c'> >));
248 
249         typedef mpl::next<i2>::type i3;
250         BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i3>::type, mpl::char_<'d'> >));
251 
252         typedef mpl::next<i3>::type i4;
253         BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i4>::type, mpl::char_<'e'> >));
254 
255         typedef mpl::next<i4>::type i5;
256         BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i5>::type, mpl::char_<'f'> >));
257 
258         typedef mpl::next<i5>::type i6;
259         BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i6>::type, mpl::char_<'g'> >));
260 
261         typedef mpl::next<i6>::type i7;
262         BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i7>::type, mpl::char_<'h'> >));
263 
264         typedef mpl::next<i7>::type i8;
265         BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i8>::type, mpl::char_<'i'> >));
266 
267         typedef mpl::next<i8>::type i9;
268         BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i9>::type, mpl::char_<'j'> >));
269     }
270 
271     // testing push_back
272     {
273         typedef mpl::push_back<mpl::string<>, mpl::char_<'a'> >::type t1;
274         BOOST_MPL_ASSERT((boost::is_same<t1, mpl::string<'a'> >));
275 
276         typedef mpl::push_back<t1, mpl::char_<'b'> >::type t2;
277         BOOST_MPL_ASSERT((boost::is_same<t2, mpl::string<'ab'> >));
278 
279         typedef mpl::push_back<t2, mpl::char_<'c'> >::type t3;
280         BOOST_MPL_ASSERT((boost::is_same<t3, mpl::string<'abc'> >));
281 
282         typedef mpl::push_back<t3, mpl::char_<'d'> >::type t4;
283         BOOST_MPL_ASSERT((boost::is_same<t4, mpl::string<'abcd'> >));
284 
285         typedef mpl::push_back<t4, mpl::char_<'e'> >::type t5;
286         BOOST_MPL_ASSERT((boost::is_same<t5, mpl::string<'abcd','e'> >));
287 
288         typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaa'> almost_full;
289         typedef mpl::push_back<almost_full, mpl::char_<'X'> >::type t6;
290         BOOST_MPL_ASSERT((boost::is_same<t6, mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaX'> >));
291 
292         typedef mpl::string<'a','a','a','a','a','a','a','aaaa'> must_repack;
293         typedef mpl::push_back<must_repack, mpl::char_<'X'> >::type t7;
294         BOOST_MPL_ASSERT((boost::is_same<t7, mpl::string<'aaaa','aaaa','aaaX'> >));
295     }
296 
297     BOOST_MPL_ASSERT((mpl::empty<mpl::string<> >));
298     BOOST_MPL_ASSERT_NOT((mpl::empty<mpl::string<'hi!'> >));
299 
300     // testing push_front
301     {
302         typedef mpl::push_front<mpl::string<>, mpl::char_<'a'> >::type t1;
303         BOOST_MPL_ASSERT((boost::is_same<t1, mpl::string<'a'> >));
304 
305         typedef mpl::push_front<t1, mpl::char_<'b'> >::type t2;
306         BOOST_MPL_ASSERT((boost::is_same<t2, mpl::string<'ba'> >));
307 
308         typedef mpl::push_front<t2, mpl::char_<'c'> >::type t3;
309         BOOST_MPL_ASSERT((boost::is_same<t3, mpl::string<'cba'> >));
310 
311         typedef mpl::push_front<t3, mpl::char_<'d'> >::type t4;
312         BOOST_MPL_ASSERT((boost::is_same<t4, mpl::string<'dcba'> >));
313 
314         typedef mpl::push_front<t4, mpl::char_<'e'> >::type t5;
315         BOOST_MPL_ASSERT((boost::is_same<t5, mpl::string<'e','dcba'> >));
316 
317         typedef mpl::string<'aaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'> almost_full;
318         typedef mpl::push_front<almost_full, mpl::char_<'X'> >::type t6;
319         BOOST_MPL_ASSERT((boost::is_same<t6, mpl::string<'Xaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'> >));
320 
321         typedef mpl::string<'aaaa','a','a','a','a','a','a','a'> must_repack;
322         typedef mpl::push_front<must_repack, mpl::char_<'X'> >::type t7;
323         BOOST_MPL_ASSERT((boost::is_same<t7, mpl::string<'Xaaa','aaaa','aaaa'> >));
324     }
325 
326     // Test c_str<>
327     BOOST_TEST(0 == std::strcmp(
328         mpl::c_str<mpl::string<> >::value
329                              , ""
330     ));
331 
332     BOOST_TEST(0 == std::strcmp(
333         mpl::c_str<mpl::string<'Hell','o wo','rld!'> >::value
334                              , "Hell" "o wo" "rld!"
335     ));
336 
337     BOOST_TEST(0 == std::strcmp(
338         mpl::c_str<mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaX'> >::value
339                              , "aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaX"
340     ));
341 
342     // test using a string as a template parameter
343     greeting<mpl::c_str<mpl::string<'Hell','o wo','rld!'> >::value> g;
344     BOOST_TEST("Hello world!" == g.say_hello());
345 
346     std::string result;
347     mpl::for_each<mpl::string<'Hell','o wo','rld!'> >(push_char(result));
348     BOOST_TEST("Hello world!" == result);
349 
350     BOOST_TEST(('h' == mpl::front<mpl::string<'hi!'> >::type()));
351     BOOST_TEST(('!' == mpl::back<mpl::string<'hi!'> >::type()));
352 
353     // back-inserter with copy
354     typedef mpl::vector_c<char, 'a','b','c','d','e'> rgc;
355     BOOST_TEST(0 == std::strcmp("abcde", mpl::c_str<rgc>::value));
356     typedef mpl::copy<rgc, mpl::back_inserter<mpl::string<> > >::type str;
357     BOOST_TEST(0 == std::strcmp("abcde", mpl::c_str<str>::value));
358 
359     // test insert_range and erase
360     {
361         typedef mpl::string<'Hell','o wo','rld!'> hello;
362         typedef mpl::advance_c<mpl::begin<hello>::type, 5>::type where;
363         typedef mpl::string<' cru','el'> cruel;
364         typedef mpl::insert_range<hello, where, cruel>::type hello_cruel;
365         BOOST_TEST(0 == std::strcmp("Hello cruel world!", mpl::c_str<hello_cruel>::value));
366 
367         typedef mpl::erase<hello, mpl::begin<hello>::type, where>::type erased1;
368         BOOST_TEST(0 == std::strcmp(" world!", mpl::c_str<erased1>::value));
369     }
370 
371     // test pop_front
372     {
373         BOOST_MPL_ASSERT((
374             boost::is_same<
375                 mpl::pop_front<mpl::string<'a'> >::type
376               , mpl::string<>
377             >
378         ));
379 
380         BOOST_MPL_ASSERT((
381             boost::is_same<
382                 mpl::pop_front<mpl::string<'ab'> >::type
383               , mpl::string<'b'>
384             >
385         ));
386 
387         BOOST_MPL_ASSERT((
388             boost::is_same<
389                 mpl::pop_front<mpl::string<'abc'> >::type
390               , mpl::string<'bc'>
391             >
392         ));
393 
394         BOOST_MPL_ASSERT((
395             boost::is_same<
396                 mpl::pop_front<mpl::string<'abcd'> >::type
397               , mpl::string<'bcd'>
398             >
399         ));
400 
401         BOOST_MPL_ASSERT((
402             boost::is_same<
403                 mpl::pop_front<mpl::string<'abcd','e'> >::type
404               , mpl::string<'bcd','e'>
405             >
406         ));
407 
408         BOOST_MPL_ASSERT((
409             boost::is_same<
410                 mpl::pop_front<mpl::string<'d','e'> >::type
411               , mpl::string<'e'>
412             >
413         ));
414 
415         BOOST_MPL_ASSERT((
416             boost::is_same<
417                 mpl::pop_front<mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'> >::type
418               , mpl::string<'aaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'>
419             >
420         ));
421     }
422 
423     // test pop_back
424     {
425         BOOST_MPL_ASSERT((
426             boost::is_same<
427                 mpl::pop_back<mpl::string<'a'> >::type
428               , mpl::string<>
429             >
430         ));
431 
432         BOOST_MPL_ASSERT((
433             boost::is_same<
434                 mpl::pop_back<mpl::string<'ab'> >::type
435               , mpl::string<'a'>
436             >
437         ));
438 
439         BOOST_MPL_ASSERT((
440             boost::is_same<
441                 mpl::pop_back<mpl::string<'abc'> >::type
442               , mpl::string<'ab'>
443             >
444         ));
445 
446         BOOST_MPL_ASSERT((
447             boost::is_same<
448                 mpl::pop_back<mpl::string<'abcd'> >::type
449               , mpl::string<'abc'>
450             >
451         ));
452 
453         BOOST_MPL_ASSERT((
454             boost::is_same<
455                 mpl::pop_back<mpl::string<'abcd','e'> >::type
456               , mpl::string<'abcd'>
457             >
458         ));
459 
460         BOOST_MPL_ASSERT((
461             boost::is_same<
462                 mpl::pop_back<mpl::string<'d','e'> >::type
463               , mpl::string<'d'>
464             >
465         ));
466 
467         BOOST_MPL_ASSERT((
468             boost::is_same<
469                 mpl::pop_back<mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'> >::type
470               , mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaa'>
471             >
472         ));
473     }
474 
475     {
476         BOOST_TEST((
477             mpl::at_c<
478                 mpl::string<'\x7f'>
479               , 0
480             >::type::value == (char)0x7f
481         ));
482 
483         BOOST_TEST((
484             mpl::at_c<
485                 mpl::string<'\x80'>
486               , 0
487             >::type::value == (char)0x80
488         ));
489 
490         BOOST_TEST((
491             mpl::at_c<
492                 mpl::string<
493                     mpl::at_c<
494                         mpl::string<'\x7f'>
495                       , 0
496                     >::type::value
497                 >
498               , 0
499             >::type::value == (char)0x7f
500         ));
501 
502         BOOST_TEST((
503             mpl::at_c<
504                 mpl::string<
505                     mpl::at_c<
506                         mpl::string<'\x80'>
507                       , 0
508                     >::type::value
509                 >
510               , 0
511             >::type::value == (char)0x80
512         ));
513     }
514 
515     return boost::report_errors();
516 }
517