1 | // |
---|---|
2 | // Boost.Pointer Container |
3 | // |
4 | // Copyright Thorsten Ottosen 2003-2005. Use, modification and |
5 | // distribution is subject to the Boost Software License, Version |
6 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
7 | // http://www.boost.org/LICENSE_1_0.txt) |
8 | // |
9 | // For more information, see http://www.boost.org/libs/ptr_container/ |
10 | // |
11 | |
12 | #include "test_data.hpp" |
13 | #include <boost/ptr_container/ptr_vector.hpp> |
14 | #include <boost/utility.hpp> |
15 | #include <algorithm> |
16 | #include <iostream> |
17 | |
18 | using namespace std; |
19 | using namespace boost; |
20 | |
21 | // |
22 | // Forward declare 'allocate_clone()' to be able |
23 | // use clonability of 'Composite' inline in the class. |
24 | // This is normally not needed when using .hpp + .cpp files. |
25 | // |
26 | class Composite; |
27 | Composite* new_clone( const Composite& ); |
28 | |
29 | |
30 | class Composite |
31 | { |
32 | typedef ptr_vector<Composite> composite_t; |
33 | typedef composite_t::iterator iterator; |
34 | typedef composite_t::const_iterator const_iterator; |
35 | typedef composite_t::size_type size_type; |
36 | composite_t elements_; |
37 | |
38 | // |
39 | // only used internally for 'clone()' |
40 | // |
41 | Composite( const Composite& r ) : elements_( r.elements_.clone() ) |
42 | { } |
43 | |
44 | // |
45 | // this class is not Copyable nor Assignable |
46 | // |
47 | void operator=( const Composite& ); |
48 | |
49 | public: |
50 | Composite() |
51 | { } |
52 | |
53 | // |
54 | // of course detructor is virtual |
55 | // |
56 | virtual ~Composite() |
57 | { } |
58 | |
59 | // |
60 | // one way of adding new elements |
61 | // |
62 | void add( Composite* c ) |
63 | { |
64 | elements_.push_back( x: c ); |
65 | } |
66 | |
67 | // |
68 | // second way of adding new elements |
69 | // |
70 | void add( Composite& c ) |
71 | { |
72 | elements_.push_back( x: new_clone( c ) ); |
73 | } |
74 | |
75 | void remove( iterator where ) |
76 | { |
77 | elements_.erase( x: where ); |
78 | } |
79 | |
80 | // |
81 | // recusively count the elements |
82 | // |
83 | size_type size() const |
84 | { |
85 | size_type res = 0; |
86 | for( const_iterator i = elements_.begin(); i != elements_.end(); ++i ) |
87 | res += i->size(); |
88 | return 1 /* this */ + res; |
89 | } |
90 | |
91 | void foo() |
92 | { |
93 | do_foo(); |
94 | for( iterator i = elements_.begin(); i != elements_.end(); ++i ) |
95 | i->foo(); |
96 | } |
97 | |
98 | // |
99 | // this class is clonable and this is the callback for 'allocate_clone()' |
100 | // |
101 | Composite* clone() const |
102 | { |
103 | return do_clone(); |
104 | } |
105 | |
106 | private: |
107 | virtual void do_foo() |
108 | { |
109 | cout << "composite base"<< "\n"; |
110 | } |
111 | |
112 | virtual Composite* do_clone() const |
113 | { |
114 | return new Composite( *this ); |
115 | } |
116 | }; |
117 | |
118 | // |
119 | // make 'Composite' clonable; note that we do not need to overload |
120 | // the function in the 'boost' namespace. |
121 | // |
122 | Composite* new_clone( const Composite& c ) |
123 | { |
124 | return c.clone(); |
125 | } |
126 | |
127 | |
128 | class ConcreteComposite1 : public Composite |
129 | { |
130 | virtual void do_foo() |
131 | { |
132 | cout << "composite 1"<< "\n"; |
133 | } |
134 | |
135 | virtual Composite* do_clone() const |
136 | { |
137 | return new ConcreteComposite1(); |
138 | } |
139 | }; |
140 | |
141 | |
142 | class ConcreteComposite2 : public Composite |
143 | { |
144 | virtual void do_foo() |
145 | { |
146 | cout << "composite 2"<< "\n"; |
147 | } |
148 | |
149 | virtual Composite* do_clone() const |
150 | { |
151 | return new ConcreteComposite2(); |
152 | } |
153 | }; |
154 | |
155 | void test_incomplete() |
156 | { |
157 | Composite c; |
158 | c.add( c: new ConcreteComposite1 ); |
159 | c.add( c: new ConcreteComposite2 ); |
160 | BOOST_CHECK_EQUAL( c.size(), 3u ); |
161 | c.add( c: new_clone( c ) ); // add c to itself |
162 | BOOST_CHECK_EQUAL( c.size(), 6u ); |
163 | c.add( c ); // add c to itself |
164 | BOOST_CHECK_EQUAL( c.size(), 12u ); |
165 | c.foo(); |
166 | } |
167 | |
168 | using namespace boost; |
169 | |
170 | |
171 | #include <boost/test/unit_test.hpp> |
172 | using boost::unit_test::test_suite; |
173 | |
174 | test_suite* init_unit_test_suite( int argc, char* argv[] ) |
175 | { |
176 | test_suite* test = BOOST_TEST_SUITE( "Pointer Container Test Suite"); |
177 | |
178 | test->add( BOOST_TEST_CASE( &test_incomplete ) ); |
179 | |
180 | return test; |
181 | } |
182 | |
183 | // |
184 | // todo: remake example with shared_ptr |
185 | // |
186 | |
187 |