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