Skip to content

Commit a715017

Browse files
committed
Moved shared_container_iterator.hpp in iterator directory, modernized code.
shared_container_iterator now uses std::shared_ptr to store the reference to the container. boost::shared_ptr is still supported and is wrapped into std::shared_ptr on construction, so there is overhead due to allocation of std::shared_ptr state. Going forward, std::shared_ptr is expected to be the primary use case. As a bonus, this eliminates the dependency on Boost.SmartPtr. Moved shared_container_iterator.hpp into the iterator directory and left a forwarding header for backward compatibility.
1 parent e446c6e commit a715017

File tree

9 files changed

+230
-123
lines changed

9 files changed

+230
-123
lines changed

CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ target_link_libraries(boost_iterator
2222
Boost::fusion
2323
Boost::mpl
2424
Boost::optional
25-
Boost::smart_ptr
2625
Boost::type_traits
2726
Boost::utility
2827
)

build.jam

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ constant boost_dependencies :
1414
/boost/fusion//boost_fusion
1515
/boost/mpl//boost_mpl
1616
/boost/optional//boost_optional
17-
/boost/smart_ptr//boost_smart_ptr
1817
/boost/type_traits//boost_type_traits
1918
/boost/utility//boost_utility ;
2019

doc/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ <h1><a class="toc-backref" href="#id25">Specialized Adaptors</a></h1>
140140
bidirectional sequence in reverse. Corrects many of the
141141
shortcomings of C++98's <tt class="docutils literal"><span class="pre">std::reverse_iterator</span></tt>.</li>
142142
<li><a class="reference external" href="../../utility/shared_container_iterator.html"><tt class="docutils literal"><span class="pre">shared_container_iterator</span></tt></a>: an iterator over elements of a container whose
143-
lifetime is maintained by a <a class="reference external" href="../../smart_ptr/shared_ptr.htm"><tt class="docutils literal"><span class="pre">shared_ptr</span></tt></a> stored in the iterator.</li>
143+
lifetime is maintained by a <tt class="docutils literal"><span class="pre">shared_ptr</span></tt> stored in the iterator.</li>
144144
<li><a class="reference external" href="transform_iterator.html"><tt class="docutils literal"><span class="pre">transform_iterator</span></tt></a> (<a class="reference external" href="transform_iterator.pdf">PDF</a>): an iterator over elements which are the result of
145145
applying some functional transformation to the elements of an
146146
underlying sequence. This component also replaces the old

doc/quickbook/shared_container_iterator.qbk

Lines changed: 78 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[section:shared_container Shared Container Iterator]
22

3-
Defined in header [@../../../boost/shared_container_iterator.hpp `boost/shared_container_iterator.hpp`].
3+
Defined in header [@../../../boost/iterator/shared_container_iterator.hpp `boost/iterator/shared_container_iterator.hpp`].
44

55
The purpose of the shared container iterator is to attach the lifetime
66
of a container to the lifetime of its iterators. In other words, the
@@ -24,9 +24,22 @@ iterator.
2424
[h2 Synopsis]
2525

2626
namespace boost {
27+
namespace iterators {
2728
template <typename Container>
2829
class shared_container_iterator;
2930

31+
template <typename Container>
32+
shared_container_iterator<Container>
33+
make_shared_container_iterator(typename Container::iterator base,
34+
std::shared_ptr<Container> const& container);
35+
36+
std::pair<
37+
typename shared_container_iterator<Container>,
38+
typename shared_container_iterator<Container>
39+
>
40+
make_shared_container_range(std::shared_ptr<Container> const& container);
41+
42+
// Backward compatibility with boost::shared_ptr
3043
template <typename Container>
3144
shared_container_iterator<Container>
3245
make_shared_container_iterator(typename Container::iterator base,
@@ -38,6 +51,15 @@ iterator.
3851
>
3952
make_shared_container_range(boost::shared_ptr<Container> const& container);
4053
}
54+
}
55+
56+
[note `shared_container_iterator` and its factory functions support both
57+
`std::shared_ptr` and `boost::shared_ptr` for a smart pointer that holds
58+
a shared reference to the container. However, the support for `boost::shared_ptr`
59+
comes at a cost of wrapping it in a `std::shared_ptr` internally. This means
60+
that when constructing the iterator from a `boost::shared_ptr`, the construction
61+
will have to allocate memory for `std::shared_ptr` shared state, which may
62+
potentially fail. It is recommended to use `std::shared_ptr` directly.]
4163

4264
[section:shared_container_type The Shared Container Iterator Type]
4365

@@ -57,18 +79,17 @@ the underlying vector and thereby extend the container's lifetime.
5779

5880
[example_link shared_iterator_example1.cpp..`shared_iterator_example1.cpp`]:
5981

60-
#include "shared_container_iterator.hpp"
61-
#include "boost/shared_ptr.hpp"
82+
#include <boost/iterator/shared_container_iterator.hpp>
6283
#include <algorithm>
6384
#include <iostream>
6485
#include <vector>
86+
#include <memory>
6587

66-
typedef boost::shared_container_iterator< std::vector<int> > iterator;
67-
88+
using iterator = boost::iterators::shared_container_iterator< std::vector<int> >;
6889

69-
void set_range(iterator& i, iterator& end) {
7090

71-
boost::shared_ptr< std::vector<int> > ints(new std::vector<int>());
91+
void set_range(iterator& i, iterator& end) {
92+
std::shared_ptr< std::vector<int> > ints(new std::vector<int>());
7293

7394
ints->push_back(0);
7495
ints->push_back(1);
@@ -77,18 +98,17 @@ the underlying vector and thereby extend the container's lifetime.
7798
ints->push_back(4);
7899
ints->push_back(5);
79100

80-
i = iterator(ints->begin(),ints);
81-
end = iterator(ints->end(),ints);
101+
i = iterator(ints->begin(), ints);
102+
end = iterator(ints->end(), ints);
82103
}
83104

84105

85106
int main() {
107+
iterator i, end;
86108

87-
iterator i,end;
88-
89-
set_range(i,end);
109+
set_range(i, end);
90110

91-
std::copy(i,end,std::ostream_iterator<int>(std::cout,","));
111+
std::copy(i, end, std::ostream_iterator<int>(std::cout, ","));
92112
std::cout.put('\n');
93113

94114
return 0;
@@ -116,15 +136,25 @@ The `shared_container_iterator` type implements the member functions
116136
and operators required of the
117137
[@http://www.sgi.com/tech/stl/RandomAccessIterator.html Random Access
118138
Iterator] concept, though only operations defined for the base
119-
iterator will be valid. In addition it has the following constructor:
139+
iterator will be valid. In addition it has the following constructors:
120140

141+
shared_container_iterator(Container::iterator const& it,
142+
std::shared_ptr<Container> const& container)
143+
144+
// Backward compatibility with boost::shared_ptr
121145
shared_container_iterator(Container::iterator const& it,
122146
boost::shared_ptr<Container> const& container)
123147

124148
[endsect]
125149

126150
[section:shared_container_object_generator The Shared Container Iterator Object Generator]
127151

152+
template <typename Container>
153+
shared_container_iterator<Container>
154+
make_shared_container_iterator(Container::iterator base,
155+
std::shared_ptr<Container> const& container)
156+
157+
// Backward compatibility with boost::shared_ptr
128158
template <typename Container>
129159
shared_container_iterator<Container>
130160
make_shared_container_iterator(Container::iterator base,
@@ -142,25 +172,23 @@ uses `make_shared_container_iterator()` to create the iterators.
142172

143173
[example_link shared_iterator_example2.cpp..`shared_iterator_example2.cpp`]:
144174

145-
#include "shared_container_iterator.hpp"
146-
#include "boost/shared_ptr.hpp"
175+
#include <boost/iterator/shared_container_iterator.hpp>
147176
#include <algorithm>
148177
#include <iterator>
149178
#include <iostream>
150179
#include <vector>
180+
#include <memory>
151181

152182

153183
template <typename Iterator>
154-
void print_range_nl (Iterator begin, Iterator end) {
155-
typedef typename std::iterator_traits<Iterator>::value_type val;
156-
std::copy(begin,end,std::ostream_iterator<val>(std::cout,","));
184+
void print_range_nl(Iterator begin, Iterator end) {
185+
using val = typename std::iterator_traits<Iterator>::value_type;
186+
std::copy(begin, end, std::ostream_iterator<val>(std::cout, ","));
157187
std::cout.put('\n');
158188
}
159189

160-
161190
int main() {
162-
163-
typedef boost::shared_ptr< std::vector<int> > ints_t;
191+
using ints_t = std::shared_ptr< std::vector<int> >;
164192
{
165193
ints_t ints(new std::vector<int>());
166194

@@ -171,12 +199,10 @@ uses `make_shared_container_iterator()` to create the iterators.
171199
ints->push_back(4);
172200
ints->push_back(5);
173201

174-
print_range_nl(boost::make_shared_container_iterator(ints->begin(),ints),
175-
boost::make_shared_container_iterator(ints->end(),ints));
202+
print_range_nl(boost::iterators::make_shared_container_iterator(ints->begin(), ints),
203+
boost::iterators::make_shared_container_iterator(ints->end(), ints));
176204
}
177205

178-
179-
180206
return 0;
181207
}
182208

@@ -187,53 +213,61 @@ named. The output from this example is the same as the previous.
187213

188214
[section:shared_container_generator The Shared Container Iterator Range Generator]
189215

216+
template <typename Container>
217+
std::pair<
218+
shared_container_iterator<Container>,
219+
shared_container_iterator<Container>
220+
>
221+
make_shared_container_range(std::shared_ptr<Container> const& container);
222+
223+
// Backward compatibility with boost::shared_ptr
190224
template <typename Container>
191225
std::pair<
192226
shared_container_iterator<Container>,
193227
shared_container_iterator<Container>
194228
>
195229
make_shared_container_range(boost::shared_ptr<Container> const& container);
196-
Class shared_container_iterator is meant primarily to return, using iterators, a range of values that we can guarantee will be alive as long as the iterators are. This is a convenience function to do just that. It is equivalent to
197-
std::make_pair(make_shared_container_iterator(container->begin(),container),
198-
make_shared_container_iterator(container->end(),container));
230+
231+
Class `shared_container_iterator` is meant primarily to return, using iterators,
232+
a range of values that we can guarantee will be alive as long as the iterators are.
233+
This is a convenience function to do just that. It is functionally equivalent to this:
234+
235+
std::make_pair(make_shared_container_iterator(container->begin(), container),
236+
make_shared_container_iterator(container->end(), container));
199237

200238
[h2 Example]
201239

202-
In the following example, a range of values is returned as a pair of shared_container_iterator objects.
240+
In the following example, a range of values is returned as a pair of `shared_container_iterator` objects.
203241

204242
[example_link shared_iterator_example3.cpp..`shared_iterator_example3.cpp`]:
205243

206-
#include "shared_container_iterator.hpp"
207-
#include "boost/shared_ptr.hpp"
208-
#include "boost/tuple/tuple.hpp" // for boost::tie
209-
#include <algorithm> // for std::copy
244+
#include <boost/iterator/shared_container_iterator.hpp>
245+
#include <algorithm> // for std::copy
210246
#include <iostream>
211247
#include <vector>
248+
#include <memory>
249+
#include <tuple> // for std::tie
212250

213251

214-
typedef boost::shared_container_iterator< std::vector<int> > iterator;
252+
using iterator = boost::iterators::shared_container_iterator< std::vector<int> >;
215253

216-
std::pair<iterator,iterator>
254+
std::pair<iterator, iterator>
217255
return_range() {
218-
boost::shared_ptr< std::vector<int> > range(new std::vector<int>());
256+
std::shared_ptr< std::vector<int> > range(new std::vector<int>());
219257
range->push_back(0);
220258
range->push_back(1);
221259
range->push_back(2);
222260
range->push_back(3);
223261
range->push_back(4);
224262
range->push_back(5);
225-
return boost::make_shared_container_range(range);
263+
return boost::iterators::make_shared_container_range(range);
226264
}
227265

228-
229266
int main() {
230-
231-
232267
iterator i,end;
268+
std::tie(i, end) = return_range();
233269

234-
boost::tie(i,end) = return_range();
235-
236-
std::copy(i,end,std::ostream_iterator<int>(std::cout,","));
270+
std::copy(i, end, std::ostream_iterator<int>(std::cout, ","));
237271
std::cout.put('\n');
238272

239273
return 0;
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
// (C) Copyright Ronald Garcia 2002. Permission to copy, use, modify, sell and
2+
// distribute this software is granted provided this copyright notice appears
3+
// in all copies. This software is provided "as is" without express or implied
4+
// warranty, and with no claim as to its suitability for any purpose.
5+
6+
// See http://www.boost.org/libs/utility/shared_container_iterator.html for documentation.
7+
8+
#ifndef BOOST_ITERATOR_SHARED_CONTAINER_ITERATOR_HPP_INCLUDED_
9+
#define BOOST_ITERATOR_SHARED_CONTAINER_ITERATOR_HPP_INCLUDED_
10+
11+
#include <memory>
12+
#include <utility>
13+
#include <boost/iterator/iterator_adaptor.hpp>
14+
15+
namespace boost {
16+
17+
// For backward compatibility with boost::shared_ptr
18+
template< class T >
19+
class shared_ptr;
20+
21+
namespace iterators {
22+
namespace detail {
23+
24+
// Fake deleter that holds an instance of boost::shared_ptr and through it keeps the pointed object from deletion
25+
template< typename T >
26+
class shared_container_iterator_bsptr_holder
27+
{
28+
private:
29+
boost::shared_ptr< T > m_ptr;
30+
31+
public:
32+
explicit shared_container_iterator_bsptr_holder(boost::shared_ptr< T > const& ptr) :
33+
m_ptr(ptr)
34+
{}
35+
36+
void operator()(T*) const noexcept {}
37+
};
38+
39+
} // namespace detail
40+
41+
template< typename Container >
42+
class shared_container_iterator :
43+
public iterator_adaptor<
44+
shared_container_iterator< Container >,
45+
typename Container::iterator
46+
>
47+
{
48+
private:
49+
using super_t = iterator_adaptor<
50+
shared_container_iterator< Container >,
51+
typename Container::iterator
52+
>;
53+
54+
using iterator_t = typename Container::iterator;
55+
using container_ref_t = std::shared_ptr< Container >;
56+
57+
public:
58+
shared_container_iterator() = default;
59+
60+
shared_container_iterator(iterator_t const& x, container_ref_t const& c) :
61+
super_t(x),
62+
m_container_ref(c)
63+
{}
64+
65+
// Constructor for backward compatibility with boost::shared_ptr
66+
shared_container_iterator(iterator_t const& x, boost::shared_ptr< Container > const& c) :
67+
super_t(x),
68+
m_container_ref(c.get(), detail::shared_container_iterator_bsptr_holder< Container >(c))
69+
{}
70+
71+
private:
72+
container_ref_t m_container_ref;
73+
};
74+
75+
template< typename Container >
76+
inline shared_container_iterator< Container >
77+
make_shared_container_iterator(typename Container::iterator iter, std::shared_ptr< Container > const& container)
78+
{
79+
return shared_container_iterator< Container >(iter, container);
80+
}
81+
82+
template< typename Container >
83+
inline std::pair< shared_container_iterator< Container >, shared_container_iterator< Container > >
84+
make_shared_container_range(std::shared_ptr< Container > const& container)
85+
{
86+
return std::make_pair
87+
(
88+
iterators::make_shared_container_iterator(container->begin(), container),
89+
iterators::make_shared_container_iterator(container->end(), container)
90+
);
91+
}
92+
93+
// Factory functions for backward compatibility with boost::shared_ptr
94+
template< typename Container >
95+
inline shared_container_iterator< Container >
96+
make_shared_container_iterator(typename Container::iterator iter, boost::shared_ptr< Container > const& container)
97+
{
98+
return shared_container_iterator< Container >(iter, container);
99+
}
100+
101+
template< typename Container >
102+
inline std::pair< shared_container_iterator< Container >, shared_container_iterator< Container > >
103+
make_shared_container_range(boost::shared_ptr< Container > const& container)
104+
{
105+
std::shared_ptr< Container > c(container.get(), detail::shared_container_iterator_bsptr_holder< Container >(container));
106+
return iterators::make_shared_container_range(std::move(c));
107+
}
108+
109+
} // namespace iterators
110+
111+
using iterators::shared_container_iterator;
112+
using iterators::make_shared_container_iterator;
113+
using iterators::make_shared_container_range;
114+
115+
} // namespace boost
116+
117+
#endif // BOOST_ITERATOR_SHARED_CONTAINER_ITERATOR_HPP_INCLUDED_

0 commit comments

Comments
 (0)