1 <?xml version=
"1.0" encoding=
"utf-8" ?>
2 <!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3 <html xmlns=
"http://www.w3.org/1999/xhtml" xml:
lang=
"en" lang=
"en">
5 <meta http-equiv=
"Content-Type" content=
"text/html; charset=utf-8" />
6 <meta name=
"generator" content=
"Docutils 0.3.10: http://docutils.sourceforge.net/" />
7 <title>Boost Pointer Container Library
</title>
8 <style type=
"text/css">
11 :Author: David Goodger
12 :Contact: goodger@users.sourceforge.net
15 :Copyright: This stylesheet has been placed in the public domain.
17 Default cascading style sheet for the HTML output of Docutils.
19 See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
20 customize this style sheet.
23 /*
"! important" is used here to override other ``margin-top`` and
24 ``margin-bottom`` styles that are later in the stylesheet or
25 more specific. See http://www.w3.org/TR/CSS1#the-cascade */
27 margin-top:
0 ! important }
29 .last, .with-subtitle {
30 margin-bottom:
0 ! important }
36 text-decoration: none ;
43 margin-bottom:
0.5em }
45 /* Uncomment (and remove this text!) to get bold-faced definition list terms
53 div.abstract p.topic-title {
57 div.admonition, div.attention, div.caution, div.danger, div.error,
58 div.hint, div.important, div.note, div.tip, div.warning {
60 border: medium outset ;
63 div.admonition p.admonition-title, div.hint p.admonition-title,
64 div.important p.admonition-title, div.note p.admonition-title,
65 div.tip p.admonition-title {
67 font-family: sans-serif }
69 div.attention p.admonition-title, div.caution p.admonition-title,
70 div.danger p.admonition-title, div.error p.admonition-title,
71 div.warning p.admonition-title {
74 font-family: sans-serif }
76 /* Uncomment (and remove this text!) to get reduced vertical space in
78 div.compound .compound-first, div.compound .compound-middle {
79 margin-bottom:
0.5em }
81 div.compound .compound-last, div.compound .compound-middle {
90 div.dedication p.topic-title {
97 div.footer, div.header {
106 div.line-block div.line-block {
113 border: medium outset ;
115 background-color: #ffffee ;
120 div.sidebar p.rubric {
121 font-family: sans-serif ;
124 div.system-messages {
127 div.system-messages h1 {
131 border: medium outset ;
134 div.system-message p.system-message-title {
141 h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
142 h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
163 ol.simple, ul.simple {
167 list-style: decimal }
170 list-style: lower-alpha }
173 list-style: upper-alpha }
176 list-style: lower-roman }
179 list-style: upper-roman }
193 white-space: nowrap }
202 font-family: sans-serif ;
207 font-family: sans-serif ;
223 pre.literal-block, pre.doctest-block {
226 background-color: #eeeeee }
229 font-family: sans-serif ;
230 font-style: oblique }
232 span.classifier-delimiter {
233 font-family: sans-serif ;
237 font-family: sans-serif }
240 white-space: nowrap }
248 span.section-subtitle {
249 /* font-size relative to parent (h1..h6 element) */
253 border-left: solid thin gray }
260 margin-bottom:
0.5em }
263 border-left: solid thin black }
265 table.docutils td, table.docutils th,
266 table.docinfo td, table.docinfo th {
267 padding-left:
0.5em ;
268 padding-right:
0.5em ;
269 vertical-align: top }
271 table.docutils th.field-name, table.docinfo th.docinfo-name {
274 white-space: nowrap ;
277 h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
278 h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
282 background-color: #eeeeee }
285 list-style-type: none }
290 <div class=
"document" id=
"boost-pointer-container-library">
291 <h1 class=
"title"><img alt=
"Boost" src=
"boost.png" /> Pointer Container Library
</h1>
292 <h2 class=
"subtitle" id=
"tutorial">Tutorial
</h2>
293 <p>The tutorial shows you the most simple usage of the
294 library. It is assumed that the reader is familiar
295 with the use of standard containers. Although
296 the tutorial is devided into sections, it is recommended
297 that you read it all from top to bottom.
</p>
299 <li><a class=
"reference" href=
"#basic-usage">Basic usage
</a></li>
300 <li><a class=
"reference" href=
"#indirected-interface">Indirected interface
</a></li>
301 <li><a class=
"reference" href=
"#sequence-containers">Sequence containers
</a></li>
302 <li><a class=
"reference" href=
"#associative-containers">Associative containers
</a></li>
303 <li><a class=
"reference" href=
"#null-values">Null values
</a></li>
304 <li><a class=
"reference" href=
"#cloneability">Cloneability
</a></li>
305 <li><a class=
"reference" href=
"#new-functions">New functions
</a></li>
306 <li><a class=
"reference" href=
"#std-auto-ptr-u-overloads">std::auto_ptr
<U
> overloads
</a></li>
307 <li><a class=
"reference" href=
"#algorithms">Algorithms
</a></li>
309 <div class=
"section">
310 <h1><a id=
"basic-usage" name=
"basic-usage">Basic usage
</a></h1>
311 <p>The most important aspect of a pointer container is that it manages
312 memory for you. This means that you in most cases do not need to worry
313 about deleting memory.
</p>
314 <p>Let us assume that we have an OO-hierarchy of animals
</p>
315 <pre class=
"literal-block">
316 class animal :
<a class=
"reference" href=
"http://www.boost.org/libs/utility/utility.htm#Class_noncopyable">boost::noncopyable
</a>
320 virtual void eat() =
0;
321 virtual int age() const =
0;
325 class mammal : public animal
330 class bird : public animal
335 <p>Then the managing of the animals is straight-forward. Imagine a
337 <pre class=
"literal-block">
340 boost::ptr_vector
<animal
> the_animals;
343 void add_animal( animal* a )
345 the_animals.push_back( a );
349 <p>Notice how we just pass the class name to the container; there
350 is no
<tt class=
"docutils literal"><span class=
"pre">*
</span></tt> to indicate it is a pointer.
351 With this declaration we can now say:
</p>
352 <pre class=
"literal-block">
354 the_zoo.add_animal( new mammal(
"joe
") );
355 the_zoo.add_animal( new bird(
"dodo
") );
357 <p>Thus we heap-allocate all elements of the container
358 and never rely on copy-semantics.
</p>
360 <div class=
"section">
361 <h1><a id=
"indirected-interface" name=
"indirected-interface">Indirected interface
</a></h1>
362 <p>A particular feature of the pointer containers is that
363 the query interface is indirected. For example,
</p>
364 <pre class=
"literal-block">
365 boost::ptr_vector
<animal
> vec;
366 vec.push_back( new animal ); // you add it as pointer ...
367 vec[
0].eat(); // but get a reference back
369 <p>This indirection also happens to iterators, so
</p>
370 <pre class=
"literal-block">
371 typedef std::vector
<animal*
> std_vec;
374 std_vec::iterator i = vec.begin();
375 (*i)-
>eat(); // '*' needed
378 <pre class=
"literal-block">
379 typedef boost::ptr_vector
<animal
> ptr_vec;
381 ptr_vec::iterator i = vec.begin();
382 i-
>eat(); // no indirection needed
385 <div class=
"section">
386 <h1><a id=
"sequence-containers" name=
"sequence-containers">Sequence containers
</a></h1>
387 <p>The sequence containers are used when you do not need to
388 keep an ordering on your elements. You can basically
389 expect all operations of the normal standard containers
390 to be available. So, for example, with a
<tt class=
"docutils literal"><span class=
"pre">ptr_deque
</span></tt>
391 and
<tt class=
"docutils literal"><span class=
"pre">ptr_list
</span></tt> object you can say:
</p>
392 <pre class=
"literal-block">
393 boost::ptr_deque
<animal
> deq;
394 deq.push_front( new animal );
397 <p>because
<tt class=
"docutils literal"><span class=
"pre">std::deque
</span></tt> and
<tt class=
"docutils literal"><span class=
"pre">std::list
</span></tt> have
<tt class=
"docutils literal"><span class=
"pre">push_front()
</span></tt>
398 and
<tt class=
"docutils literal"><span class=
"pre">pop_front()
</span></tt> members.
</p>
399 <p>If the standard sequence supports
400 random access, so does the pointer container; for example:
</p>
401 <pre class=
"literal-block">
402 for( boost::ptr_deque
<animal
>::size_type i =
0u;
403 i != deq.size(); ++i )
406 <p>The
<tt class=
"docutils literal"><span class=
"pre">ptr_vector
</span></tt> also allows you to specify the size of
407 the buffer to allocate; for example
</p>
408 <pre class=
"literal-block">
409 boost::ptr_vector
<animal
> animals(
10u );
411 <p>will reserve room for
10 animals.
</p>
413 <div class=
"section">
414 <h1><a id=
"associative-containers" name=
"associative-containers">Associative containers
</a></h1>
415 <p>To keep an ordering on our animals, we could use a
<tt class=
"docutils literal"><span class=
"pre">ptr_set
</span></tt>:
</p>
416 <pre class=
"literal-block">
417 boost::ptr_set
<animal
> set;
418 set.insert( new monkey(
"bobo
") );
419 set.insert( new whale(
"anna
") );
422 <p>This requires that
<tt class=
"docutils literal"><span class=
"pre">operator
<()
</span></tt> is defined for animals. One
423 way to do this could be
</p>
424 <pre class=
"literal-block">
425 inline bool operator
<( const animal
& l, const animal
& r )
427 return l.name()
< r.name();
430 <p>if we wanted to keep the animals sorted by name.
</p>
431 <p>Maybe you want to keep all the animals in zoo ordered wrt.
432 their name, but it so happens that many animals have the
433 same name. We can then use a
<tt class=
"docutils literal"><span class=
"pre">ptr_multimap
</span></tt>:
</p>
434 <pre class=
"literal-block">
435 typedef boost::ptr_multimap
<std::string,animal
> zoo_type;
437 std::string bobo =
"bobo
",
438 anna =
"anna
";
439 zoo.insert( bobo, new monkey(bobo) );
440 zoo.insert( bobo, new elephant(bobo) );
441 zoo.insert( anna, new whale(anna) );
442 zoo.insert( anna, new emu(anna) );
444 <p>Note that must create the key as an lvalue
445 (due to exception-safety issues); the following would not
447 <pre class=
"literal-block">
448 zoo.insert(
"bobo
", // this is bad, but you get compile error
449 new monkey(
"bobo
") );
451 <p>If a multimap is not needed, we can use
<tt class=
"docutils literal"><span class=
"pre">operator[]()
</span></tt>
452 to avoid the clumsiness:
</p>
453 <pre class=
"literal-block">
454 boost::ptr_map
<std::string,animal
> animals;
455 animals[
"bobo
"].set_name(
"bobo
");
457 <p>This requires a default constructor for animals and
458 a function to do the initialization, in this case
<tt class=
"docutils literal"><span class=
"pre">set_name()
</span></tt>.
</p>
459 <p>A better alternative is to use
<a class=
"reference" href=
"../../assign/index.html">Boost.Assign
</a>
460 to help you out. In particular, consider
</p>
462 <li><a class=
"reference" href=
"../../assign/doc/index.html#ptr_push_back">ptr_push_back(), ptr_push_front(), ptr_insert() and ptr_map_insert()
</a></li>
463 <li><a class=
"reference" href=
"../../assign/doc/index.html#ptr_list_of">ptr_list_of()
</a></li>
465 <p>For example, the above insertion may now be written
</p>
466 <pre class=
"literal-block">
467 boost::ptr_multimap
<std::string,animal
> animals;
469 using namespace boost::assign;
470 ptr_map_insert
<monkey
>( animals )(
"bobo
",
"bobo
" );
471 ptr_map_insert
<elephant
>( animals )(
"bobo
",
"bobo
" );
472 ptr_map_insert
<whale
>( animals )(
"anna
",
"anna
" );
473 ptr_map_insert
<emu
>( animals )(
"anna
",
"anna
" );
476 <div class=
"section">
477 <h1><a id=
"null-values" name=
"null-values">Null values
</a></h1>
478 <p>By default, if you try to insert null into a container, an exception
479 is thrown. If you want to allow nulls, then you must
480 say so explicitly when declaring the container variable
</p>
481 <pre class=
"literal-block">
482 boost::ptr_vector
< boost::nullable
<animal
> > animals_type;
483 animals_type animals;
485 animals.insert( animals.end(), new dodo(
"fido
") );
486 animals.insert( animals.begin(),
0 ) // ok
488 <p>Once you have inserted a null into the container, you must
489 always check if the value is null before accessing the object
</p>
490 <pre class=
"literal-block">
491 for( animals_type::iterator i = animals.begin();
492 i != animals.end(); ++i )
494 if( !boost::is_null(i) ) // always check for validity
498 <p>If the container support random access, you may also check this as
</p>
499 <pre class=
"literal-block">
500 for( animals_type::size_type i =
0u;
501 i != animals.size(); ++i )
503 if( !animals.is_null(i) )
507 <p>Note that it is meaningless to insert
508 null into
<tt class=
"docutils literal"><span class=
"pre">ptr_set
</span></tt> and
<tt class=
"docutils literal"><span class=
"pre">ptr_multiset
</span></tt>.
</p>
510 <div class=
"section">
511 <h1><a id=
"cloneability" name=
"cloneability">Cloneability
</a></h1>
512 <p>In OO programming it is typical to prohibit copying of objects; the
513 objects may sometimes be allowed to be Cloneable; for example,:
</p>
514 <pre class=
"literal-block">
515 animal* animal::clone() const
517 return do_clone(); // implemented by private virtual function
520 <p>If the OO hierarchy thus allows cloning, we need to tell the
521 pointer containers how cloning is to be done. This is simply
522 done by defining a free-standing function,
<tt class=
"docutils literal"><span class=
"pre">new_clone()
</span></tt>,
523 in the same namespace as
524 the object hierarchy:
</p>
525 <pre class=
"literal-block">
526 inline animal* new_clone( const animal
& a )
531 <p>That is all, now a lot of functions in a pointer container
532 can exploit the cloneability of the animal objects. For example
</p>
533 <pre class=
"literal-block">
534 typedef boost::ptr_list
<animal
> zoo_type;
535 zoo_type zoo, another_zoo;
537 another_zoo.assign( zoo.begin(), zoo.end() );
539 <p>will fill another zoo with clones of the first zoo. Similarly,
540 <tt class=
"docutils literal"><span class=
"pre">insert()
</span></tt> can now insert clones into your pointer container
</p>
541 <pre class=
"literal-block">
542 another_zoo.insert( another_zoo.begin(), zoo.begin(), zoo.end() );
544 <p>The whole container can now also be cloned
</p>
545 <pre class=
"literal-block">
546 zoo_type yet_another_zoo = zoo.clone();
548 <p>Copying or assigning the container has the same effect as cloning (though it is slightly cheaper):
</p>
549 <pre class=
"literal-block">
550 zoo_type yet_another_zoo = zoo;
552 <p>Copying also support derived-to-base class conversions:
</p>
553 <pre class=
"literal-block">
554 boost::ptr_vector
<monkey
> monkeys = boost::assign::ptr_list_of
<monkey
>(
"bobo
" )(
"bebe
")(
"uhuh
" );
555 boost::ptr_vector
<animal
> animals = monkeys;
557 <p>This also works for maps:
</p>
558 <pre class=
"literal-block">
559 boost::ptr_map
<std::string,monkey
> monkeys = ...;
560 boost::ptr_map
<std::string,animal
> animals = monkeys;
563 <div class=
"section">
564 <h1><a id=
"new-functions" name=
"new-functions">New functions
</a></h1>
565 <p>Given that we know we are working with pointers, a few new functions
566 make sense. For example, say you want to remove an
567 animal from the zoo
</p>
568 <pre class=
"literal-block">
569 zoo_type::auto_type the_animal = zoo.release( zoo.begin() );
570 the_animal-
>eat();
571 animal* the_animal_ptr = the_animal.release(); // now this is not deleted
572 zoo.release(
2); // for random access containers
574 <p>You can think of
<tt class=
"docutils literal"><span class=
"pre">auto_type
</span></tt> as a non-copyable form of
575 <tt class=
"docutils literal"><span class=
"pre">std::auto_ptr
</span></tt>. Notice that when you release an object, the
576 pointer is removed from the container and the containers size
577 shrinks. For containers that store nulls, we can exploit that
578 <tt class=
"docutils literal"><span class=
"pre">auto_type
</span></tt> is convertible to
<tt class=
"docutils literal"><span class=
"pre">bool
</span></tt>:
</p>
579 <pre class=
"literal-block">
580 if( ptr_vector
< nullable
<T
> >::auto_type r = vec.pop_back() )
585 <p>You can also release the entire container if you
586 want to return it from a function
</p>
587 <pre class=
"literal-block">
588 std::auto_ptr
< boost::ptr_deque
<animal
> > get_zoo()
590 boost::ptr_deque
<animal
> result;
592 return result.release(); // give up ownership
595 boost::ptr_deque
<animal
> animals = get_zoo();
597 <p>Let us assume we want to move an animal object from
598 one zoo to another. In other words, we want to move the
599 animal and the responsibility of it to another zoo
</p>
600 <pre class=
"literal-block">
601 another_zoo.transfer( another_zoo.end(), // insert before end
602 zoo.begin(), // insert this animal ...
603 zoo ); // from this container
605 <p>This kind of
"move-semantics
" is different from
606 normal value-based containers. You can think of
<tt class=
"docutils literal"><span class=
"pre">transfer()
</span></tt>
607 as the same as
<tt class=
"docutils literal"><span class=
"pre">splice()
</span></tt> on
<tt class=
"docutils literal"><span class=
"pre">std::list
</span></tt>.
</p>
608 <p>If you want to replace an element, you can easily do so
</p>
609 <pre class=
"literal-block">
610 zoo_type::auto_type old_animal = zoo.replace( zoo.begin(), new monkey(
"bibi
") );
611 zoo.replace(
2, old_animal.release() ); // for random access containers
613 <p>A map is slightly different to iterate over than standard maps.
615 <pre class=
"literal-block">
616 typedef boost::ptr_map
<std::string, boost::nullable
<animal
> > animal_map;
619 for( animal_map::const_iterator i = map.begin(), e = map.end(); i != e; ++i )
621 std::cout
<< "\n key:
" << i-
>first;
622 std::cout
<< "\n age:
";
624 if( boost::is_null(i) )
625 std::cout
<< "unknown
";
627 std::cout
<< i-
>second-
>age();
630 <p>Except for the check for null, this looks like it would with a normal map. But if
<tt class=
"docutils literal"><span class=
"pre">age()
</span></tt> had
631 not been a
<tt class=
"docutils literal"><span class=
"pre">const
</span></tt> member function,
632 it would not have compiled.
</p>
633 <p>Maps can also be indexed with bounds-checking
</p>
634 <pre class=
"literal-block">
637 animal
& bobo = map.at(
"bobo
");
639 catch( boost::bad_ptr_container_operation
& e )
641 //
"bobo
" not found
645 <div class=
"section">
646 <h1><a id=
"std-auto-ptr-u-overloads" name=
"std-auto-ptr-u-overloads"><tt class=
"docutils literal"><span class=
"pre">std::auto_ptr
<U
></span></tt> overloads
</a></h1>
647 <p>Every time there is a function that takes a
<tt class=
"docutils literal"><span class=
"pre">T*
</span></tt> parameter, there is
648 also a function taking an
<tt class=
"docutils literal"><span class=
"pre">std::auto_ptr
<U
></span></tt> parameter. This is of course done
649 to make the library intregrate seamlessly with
<tt class=
"docutils literal"><span class=
"pre">std::auto_ptr
</span></tt>. For example
</p>
650 <pre class=
"literal-block">
651 std::ptr_vector
<Base
> vec;
652 vec.push_back( new Base );
654 <p>is complemented by
</p>
655 <pre class=
"literal-block">
656 std::auto_ptr
<Derived
> p( new Derived );
659 <p>Notice that the template argument for
<tt class=
"docutils literal"><span class=
"pre">std::auto_ptr
</span></tt> does not need to
660 follow the template argument for
<tt class=
"docutils literal"><span class=
"pre">ptr_vector
</span></tt> as long as
<tt class=
"docutils literal"><span class=
"pre">Derived*
</span></tt>
661 can be implicitly converted to
<tt class=
"docutils literal"><span class=
"pre">Base*
</span></tt>.
</p>
663 <div class=
"section">
664 <h1><a id=
"algorithms" name=
"algorithms">Algorithms
</a></h1>
665 <p>Unfortunately it is not possible to use pointer containers with
666 mutating algorithms from the standard library. However,
668 are instead provided as member functions:
</p>
669 <pre class=
"literal-block">
670 boost::ptr_vector
<animal
> zoo;
672 zoo.sort(); // assume 'bool operator
<( const animal
&, const animal
& )'
673 zoo.sort( std::less
<animal
>() ); // the same, notice no '*' is present
674 zoo.sort( zoo.begin(), zoo.begin() +
5 ); // sort selected range
676 <p>Notice that predicates are automatically wrapped in an
<a class=
"reference" href=
"indirect_fun.html">indirect_fun
</a> object.
</p>
677 <p>You can remove equal and adjacent elements using
<tt class=
"docutils literal"><span class=
"pre">unique()
</span></tt>:
</p>
678 <pre class=
"literal-block">
679 zoo.unique(); // assume 'bool operator==( const animal
&, const animal
& )'
680 zoo.unique( zoo.begin(), zoo.begin() +
5, my_comparison_predicate() );
682 <p>If you just want to remove certain elements, use
<tt class=
"docutils literal"><span class=
"pre">erase_if
</span></tt>:
</p>
683 <pre class=
"literal-block">
684 zoo.erase_if( my_predicate() );
686 <p>Finally you may want to merge two sorted containers:
</p>
687 <pre class=
"literal-block">
688 boost::ptr_vector
<animal
> another_zoo = ...;
689 another_zoo.sort(); // sorted wrt. to same order as 'zoo'
690 zoo.merge( another_zoo );
691 BOOST_ASSERT( another_zoo.empty() );
693 <p>That is all; now you have learned all the basics!
</p>
694 <hr><p><strong>See also
</strong></p>
696 <li><a class=
"reference" href=
"guidelines.html">Usage guidelines
</a></li>
697 <li><a class=
"reference" href=
"../../conversion/cast.htm#Polymorphic_castl">Cast utilities
</a></li>
699 <p><strong>Navigate
</strong></p>
701 <li><a class=
"reference" href=
"ptr_container.html">home
</a></li>
702 <li><a class=
"reference" href=
"examples.html">examples
</a></li>
704 <hr><table class=
"docutils field-list" frame=
"void" rules=
"none">
705 <col class=
"field-name" />
706 <col class=
"field-body" />
708 <tr class=
"field"><th class=
"field-name">Copyright:
</th><td class=
"field-body">Thorsten Ottosen
2004-
2006. Use, modification and distribution is subject to the Boost Software License, Version
1.0 (see
<a class=
"reference" href=
"http://www.boost.org/LICENSE_1_0.txt">LICENSE_1_0.txt
</a>).
</td>