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.
This commit is contained in:
Andrey Semashev 2025-02-07 02:07:12 +03:00
parent e446c6e05c
commit a7150173ed
9 changed files with 230 additions and 123 deletions

View File

@ -22,7 +22,6 @@ target_link_libraries(boost_iterator
Boost::fusion Boost::fusion
Boost::mpl Boost::mpl
Boost::optional Boost::optional
Boost::smart_ptr
Boost::type_traits Boost::type_traits
Boost::utility Boost::utility
) )

View File

@ -14,7 +14,6 @@ constant boost_dependencies :
/boost/fusion//boost_fusion /boost/fusion//boost_fusion
/boost/mpl//boost_mpl /boost/mpl//boost_mpl
/boost/optional//boost_optional /boost/optional//boost_optional
/boost/smart_ptr//boost_smart_ptr
/boost/type_traits//boost_type_traits /boost/type_traits//boost_type_traits
/boost/utility//boost_utility ; /boost/utility//boost_utility ;

View File

@ -140,7 +140,7 @@ sequence, rearranged according to some sequence of integer indices.</li>
bidirectional sequence in reverse. Corrects many of the bidirectional sequence in reverse. Corrects many of the
shortcomings of C++98's <tt class="docutils literal"><span class="pre">std::reverse_iterator</span></tt>.</li> shortcomings of C++98's <tt class="docutils literal"><span class="pre">std::reverse_iterator</span></tt>.</li>
<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 <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
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> lifetime is maintained by a <tt class="docutils literal"><span class="pre">shared_ptr</span></tt> stored in the iterator.</li>
<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 <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
applying some functional transformation to the elements of an applying some functional transformation to the elements of an
underlying sequence. This component also replaces the old underlying sequence. This component also replaces the old

View File

@ -1,6 +1,6 @@
[section:shared_container Shared Container Iterator] [section:shared_container Shared Container Iterator]
Defined in header [@../../../boost/shared_container_iterator.hpp `boost/shared_container_iterator.hpp`]. Defined in header [@../../../boost/iterator/shared_container_iterator.hpp `boost/iterator/shared_container_iterator.hpp`].
The purpose of the shared container iterator is to attach the lifetime The purpose of the shared container iterator is to attach the lifetime
of a container to the lifetime of its iterators. In other words, the of a container to the lifetime of its iterators. In other words, the
@ -24,9 +24,22 @@ iterator.
[h2 Synopsis] [h2 Synopsis]
namespace boost { namespace boost {
namespace iterators {
template <typename Container> template <typename Container>
class shared_container_iterator; class shared_container_iterator;
template <typename Container>
shared_container_iterator<Container>
make_shared_container_iterator(typename Container::iterator base,
std::shared_ptr<Container> const& container);
std::pair<
typename shared_container_iterator<Container>,
typename shared_container_iterator<Container>
>
make_shared_container_range(std::shared_ptr<Container> const& container);
// Backward compatibility with boost::shared_ptr
template <typename Container> template <typename Container>
shared_container_iterator<Container> shared_container_iterator<Container>
make_shared_container_iterator(typename Container::iterator base, make_shared_container_iterator(typename Container::iterator base,
@ -38,6 +51,15 @@ iterator.
> >
make_shared_container_range(boost::shared_ptr<Container> const& container); make_shared_container_range(boost::shared_ptr<Container> const& container);
} }
}
[note `shared_container_iterator` and its factory functions support both
`std::shared_ptr` and `boost::shared_ptr` for a smart pointer that holds
a shared reference to the container. However, the support for `boost::shared_ptr`
comes at a cost of wrapping it in a `std::shared_ptr` internally. This means
that when constructing the iterator from a `boost::shared_ptr`, the construction
will have to allocate memory for `std::shared_ptr` shared state, which may
potentially fail. It is recommended to use `std::shared_ptr` directly.]
[section:shared_container_type The Shared Container Iterator Type] [section:shared_container_type The Shared Container Iterator Type]
@ -57,18 +79,17 @@ the underlying vector and thereby extend the container's lifetime.
[example_link shared_iterator_example1.cpp..`shared_iterator_example1.cpp`]: [example_link shared_iterator_example1.cpp..`shared_iterator_example1.cpp`]:
#include "shared_container_iterator.hpp" #include <boost/iterator/shared_container_iterator.hpp>
#include "boost/shared_ptr.hpp"
#include <algorithm> #include <algorithm>
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <memory>
typedef boost::shared_container_iterator< std::vector<int> > iterator; using iterator = boost::iterators::shared_container_iterator< std::vector<int> >;
void set_range(iterator& i, iterator& end) { void set_range(iterator& i, iterator& end) {
std::shared_ptr< std::vector<int> > ints(new std::vector<int>());
boost::shared_ptr< std::vector<int> > ints(new std::vector<int>());
ints->push_back(0); ints->push_back(0);
ints->push_back(1); ints->push_back(1);
@ -77,18 +98,17 @@ the underlying vector and thereby extend the container's lifetime.
ints->push_back(4); ints->push_back(4);
ints->push_back(5); ints->push_back(5);
i = iterator(ints->begin(),ints); i = iterator(ints->begin(), ints);
end = iterator(ints->end(),ints); end = iterator(ints->end(), ints);
} }
int main() { int main() {
iterator i, end;
iterator i,end; set_range(i, end);
set_range(i,end); std::copy(i, end, std::ostream_iterator<int>(std::cout, ","));
std::copy(i,end,std::ostream_iterator<int>(std::cout,","));
std::cout.put('\n'); std::cout.put('\n');
return 0; return 0;
@ -116,8 +136,12 @@ The `shared_container_iterator` type implements the member functions
and operators required of the and operators required of the
[@http://www.sgi.com/tech/stl/RandomAccessIterator.html Random Access [@http://www.sgi.com/tech/stl/RandomAccessIterator.html Random Access
Iterator] concept, though only operations defined for the base Iterator] concept, though only operations defined for the base
iterator will be valid. In addition it has the following constructor: iterator will be valid. In addition it has the following constructors:
shared_container_iterator(Container::iterator const& it,
std::shared_ptr<Container> const& container)
// Backward compatibility with boost::shared_ptr
shared_container_iterator(Container::iterator const& it, shared_container_iterator(Container::iterator const& it,
boost::shared_ptr<Container> const& container) boost::shared_ptr<Container> const& container)
@ -125,6 +149,12 @@ iterator will be valid. In addition it has the following constructor:
[section:shared_container_object_generator The Shared Container Iterator Object Generator] [section:shared_container_object_generator The Shared Container Iterator Object Generator]
template <typename Container>
shared_container_iterator<Container>
make_shared_container_iterator(Container::iterator base,
std::shared_ptr<Container> const& container)
// Backward compatibility with boost::shared_ptr
template <typename Container> template <typename Container>
shared_container_iterator<Container> shared_container_iterator<Container>
make_shared_container_iterator(Container::iterator base, make_shared_container_iterator(Container::iterator base,
@ -142,25 +172,23 @@ uses `make_shared_container_iterator()` to create the iterators.
[example_link shared_iterator_example2.cpp..`shared_iterator_example2.cpp`]: [example_link shared_iterator_example2.cpp..`shared_iterator_example2.cpp`]:
#include "shared_container_iterator.hpp" #include <boost/iterator/shared_container_iterator.hpp>
#include "boost/shared_ptr.hpp"
#include <algorithm> #include <algorithm>
#include <iterator> #include <iterator>
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <memory>
template <typename Iterator> template <typename Iterator>
void print_range_nl (Iterator begin, Iterator end) { void print_range_nl(Iterator begin, Iterator end) {
typedef typename std::iterator_traits<Iterator>::value_type val; using val = typename std::iterator_traits<Iterator>::value_type;
std::copy(begin,end,std::ostream_iterator<val>(std::cout,",")); std::copy(begin, end, std::ostream_iterator<val>(std::cout, ","));
std::cout.put('\n'); std::cout.put('\n');
} }
int main() { int main() {
using ints_t = std::shared_ptr< std::vector<int> >;
typedef boost::shared_ptr< std::vector<int> > ints_t;
{ {
ints_t ints(new std::vector<int>()); ints_t ints(new std::vector<int>());
@ -171,12 +199,10 @@ uses `make_shared_container_iterator()` to create the iterators.
ints->push_back(4); ints->push_back(4);
ints->push_back(5); ints->push_back(5);
print_range_nl(boost::make_shared_container_iterator(ints->begin(),ints), print_range_nl(boost::iterators::make_shared_container_iterator(ints->begin(), ints),
boost::make_shared_container_iterator(ints->end(),ints)); boost::iterators::make_shared_container_iterator(ints->end(), ints));
} }
return 0; return 0;
} }
@ -187,53 +213,61 @@ named. The output from this example is the same as the previous.
[section:shared_container_generator The Shared Container Iterator Range Generator] [section:shared_container_generator The Shared Container Iterator Range Generator]
template <typename Container>
std::pair<
shared_container_iterator<Container>,
shared_container_iterator<Container>
>
make_shared_container_range(std::shared_ptr<Container> const& container);
// Backward compatibility with boost::shared_ptr
template <typename Container> template <typename Container>
std::pair< std::pair<
shared_container_iterator<Container>, shared_container_iterator<Container>,
shared_container_iterator<Container> shared_container_iterator<Container>
> >
make_shared_container_range(boost::shared_ptr<Container> const& container); make_shared_container_range(boost::shared_ptr<Container> const& container);
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
std::make_pair(make_shared_container_iterator(container->begin(),container), Class `shared_container_iterator` is meant primarily to return, using iterators,
make_shared_container_iterator(container->end(),container)); 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 functionally equivalent to this:
std::make_pair(make_shared_container_iterator(container->begin(), container),
make_shared_container_iterator(container->end(), container));
[h2 Example] [h2 Example]
In the following example, a range of values is returned as a pair of shared_container_iterator objects. In the following example, a range of values is returned as a pair of `shared_container_iterator` objects.
[example_link shared_iterator_example3.cpp..`shared_iterator_example3.cpp`]: [example_link shared_iterator_example3.cpp..`shared_iterator_example3.cpp`]:
#include "shared_container_iterator.hpp" #include <boost/iterator/shared_container_iterator.hpp>
#include "boost/shared_ptr.hpp" #include <algorithm> // for std::copy
#include "boost/tuple/tuple.hpp" // for boost::tie
#include <algorithm> // for std::copy
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <memory>
#include <tuple> // for std::tie
typedef boost::shared_container_iterator< std::vector<int> > iterator; using iterator = boost::iterators::shared_container_iterator< std::vector<int> >;
std::pair<iterator,iterator> std::pair<iterator, iterator>
return_range() { return_range() {
boost::shared_ptr< std::vector<int> > range(new std::vector<int>()); std::shared_ptr< std::vector<int> > range(new std::vector<int>());
range->push_back(0); range->push_back(0);
range->push_back(1); range->push_back(1);
range->push_back(2); range->push_back(2);
range->push_back(3); range->push_back(3);
range->push_back(4); range->push_back(4);
range->push_back(5); range->push_back(5);
return boost::make_shared_container_range(range); return boost::iterators::make_shared_container_range(range);
} }
int main() { int main() {
iterator i,end; iterator i,end;
std::tie(i, end) = return_range();
boost::tie(i,end) = return_range(); std::copy(i, end, std::ostream_iterator<int>(std::cout, ","));
std::copy(i,end,std::ostream_iterator<int>(std::cout,","));
std::cout.put('\n'); std::cout.put('\n');
return 0; return 0;

View File

@ -0,0 +1,117 @@
// (C) Copyright Ronald Garcia 2002. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// See http://www.boost.org/libs/utility/shared_container_iterator.html for documentation.
#ifndef BOOST_ITERATOR_SHARED_CONTAINER_ITERATOR_HPP_INCLUDED_
#define BOOST_ITERATOR_SHARED_CONTAINER_ITERATOR_HPP_INCLUDED_
#include <memory>
#include <utility>
#include <boost/iterator/iterator_adaptor.hpp>
namespace boost {
// For backward compatibility with boost::shared_ptr
template< class T >
class shared_ptr;
namespace iterators {
namespace detail {
// Fake deleter that holds an instance of boost::shared_ptr and through it keeps the pointed object from deletion
template< typename T >
class shared_container_iterator_bsptr_holder
{
private:
boost::shared_ptr< T > m_ptr;
public:
explicit shared_container_iterator_bsptr_holder(boost::shared_ptr< T > const& ptr) :
m_ptr(ptr)
{}
void operator()(T*) const noexcept {}
};
} // namespace detail
template< typename Container >
class shared_container_iterator :
public iterator_adaptor<
shared_container_iterator< Container >,
typename Container::iterator
>
{
private:
using super_t = iterator_adaptor<
shared_container_iterator< Container >,
typename Container::iterator
>;
using iterator_t = typename Container::iterator;
using container_ref_t = std::shared_ptr< Container >;
public:
shared_container_iterator() = default;
shared_container_iterator(iterator_t const& x, container_ref_t const& c) :
super_t(x),
m_container_ref(c)
{}
// Constructor for backward compatibility with boost::shared_ptr
shared_container_iterator(iterator_t const& x, boost::shared_ptr< Container > const& c) :
super_t(x),
m_container_ref(c.get(), detail::shared_container_iterator_bsptr_holder< Container >(c))
{}
private:
container_ref_t m_container_ref;
};
template< typename Container >
inline shared_container_iterator< Container >
make_shared_container_iterator(typename Container::iterator iter, std::shared_ptr< Container > const& container)
{
return shared_container_iterator< Container >(iter, container);
}
template< typename Container >
inline std::pair< shared_container_iterator< Container >, shared_container_iterator< Container > >
make_shared_container_range(std::shared_ptr< Container > const& container)
{
return std::make_pair
(
iterators::make_shared_container_iterator(container->begin(), container),
iterators::make_shared_container_iterator(container->end(), container)
);
}
// Factory functions for backward compatibility with boost::shared_ptr
template< typename Container >
inline shared_container_iterator< Container >
make_shared_container_iterator(typename Container::iterator iter, boost::shared_ptr< Container > const& container)
{
return shared_container_iterator< Container >(iter, container);
}
template< typename Container >
inline std::pair< shared_container_iterator< Container >, shared_container_iterator< Container > >
make_shared_container_range(boost::shared_ptr< Container > const& container)
{
std::shared_ptr< Container > c(container.get(), detail::shared_container_iterator_bsptr_holder< Container >(container));
return iterators::make_shared_container_range(std::move(c));
}
} // namespace iterators
using iterators::shared_container_iterator;
using iterators::make_shared_container_iterator;
using iterators::make_shared_container_range;
} // namespace boost
#endif // BOOST_ITERATOR_SHARED_CONTAINER_ITERATOR_HPP_INCLUDED_

View File

@ -1,69 +1,14 @@
// (C) Copyright Ronald Garcia 2002. Permission to copy, use, modify, sell and // (C) Copyright Andrey Semashev 2025.
// distribute this software is granted provided this copyright notice appears // Distributed under the Boost Software License, Version 1.0. (See
// in all copies. This software is provided "as is" without express or implied // accompanying file LICENSE_1_0.txt or copy at
// warranty, and with no claim as to its suitability for any purpose. // http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/utility/shared_container_iterator.html for documentation.
#ifndef BOOST_SHARED_CONTAINER_ITERATOR_HPP #ifndef BOOST_SHARED_CONTAINER_ITERATOR_HPP
#define BOOST_SHARED_CONTAINER_ITERATOR_HPP #define BOOST_SHARED_CONTAINER_ITERATOR_HPP
#include "boost/iterator_adaptors.hpp" // This is a deprecated header left for backward compatibility.
#include "boost/shared_ptr.hpp" // Please use <boost/iterator/shared_container_iterator.hpp> instead.
#include <utility>
namespace boost { #include <boost/iterator/shared_container_iterator.hpp>
namespace iterators {
template <typename Container> #endif // BOOST_SHARED_CONTAINER_ITERATOR_HPP
class shared_container_iterator : public iterator_adaptor<
shared_container_iterator<Container>,
typename Container::iterator> {
typedef iterator_adaptor<
shared_container_iterator<Container>,
typename Container::iterator> super_t;
typedef typename Container::iterator iterator_t;
typedef boost::shared_ptr<Container> container_ref_t;
container_ref_t container_ref;
public:
shared_container_iterator() { }
shared_container_iterator(iterator_t const& x,container_ref_t const& c) :
super_t(x), container_ref(c) { }
};
template <typename Container>
inline shared_container_iterator<Container>
make_shared_container_iterator(typename Container::iterator iter,
boost::shared_ptr<Container> const& container) {
typedef shared_container_iterator<Container> iterator;
return iterator(iter,container);
}
template <typename Container>
inline std::pair<
shared_container_iterator<Container>,
shared_container_iterator<Container> >
make_shared_container_range(boost::shared_ptr<Container> const& container) {
return
std::make_pair(
make_shared_container_iterator(container->begin(),container),
make_shared_container_iterator(container->end(),container));
}
} // namespace iterators
using iterators::shared_container_iterator;
using iterators::make_shared_container_iterator;
using iterators::make_shared_container_range;
} // namespace boost
#endif

View File

@ -74,5 +74,5 @@ test-suite iterator
[ compile adl_test.cpp : <library>/boost/array//boost_array ] [ compile adl_test.cpp : <library>/boost/array//boost_array ]
[ compile range_distance_compat_test.cpp : <library>/boost/range//boost_range ] [ compile range_distance_compat_test.cpp : <library>/boost/range//boost_range ]
[ run shared_iterator_test.cpp ] [ run shared_iterator_test.cpp : : : <library>/boost/smart_ptr//boost_smart_ptr ]
; ;

View File

@ -14,12 +14,14 @@
// //
#include "boost/shared_container_iterator.hpp" #include <boost/iterator/shared_container_iterator.hpp>
#include "boost/shared_ptr.hpp" #include <boost/shared_ptr.hpp>
#include <boost/core/lightweight_test.hpp> #include <boost/core/lightweight_test.hpp>
#include <vector> #include <vector>
#include <memory>
struct resource { struct resource
{
static int count; static int count;
resource() { ++count; } resource() { ++count; }
resource(resource const&) { ++count; } resource(resource const&) { ++count; }
@ -27,20 +29,20 @@ struct resource {
}; };
int resource::count = 0; int resource::count = 0;
typedef std::vector<resource> resources_t; typedef std::vector< resource > resources_t;
typedef boost::shared_container_iterator< resources_t > iterator; typedef boost::shared_container_iterator< resources_t > iterator;
template< typename SharedPtr >
void set_range(iterator& i, iterator& end) { void set_range(iterator& i, iterator& end)
{
boost::shared_ptr< resources_t > objs(new resources_t()); SharedPtr objs(new resources_t());
for (int j = 0; j != 6; ++j) for (int j = 0; j != 6; ++j)
objs->push_back(resource()); objs->push_back(resource());
i = iterator(objs->begin(),objs); i = iterator(objs->begin(), objs);
end = iterator(objs->end(),objs); end = iterator(objs->end(), objs);
BOOST_TEST_EQ(resource::count, 6); BOOST_TEST_EQ(resource::count, 6);
} }
@ -53,7 +55,18 @@ int main() {
iterator i; iterator i;
{ {
iterator end; iterator end;
set_range(i,end); set_range< boost::shared_ptr< resources_t > >(i, end);
BOOST_TEST_EQ(resource::count, 6);
}
BOOST_TEST_EQ(resource::count, 6);
}
BOOST_TEST_EQ(resource::count, 0);
{
iterator i;
{
iterator end;
set_range< std::shared_ptr< resources_t > >(i, end);
BOOST_TEST_EQ(resource::count, 6); BOOST_TEST_EQ(resource::count, 6);
} }
BOOST_TEST_EQ(resource::count, 6); BOOST_TEST_EQ(resource::count, 6);

View File

@ -7,7 +7,6 @@
#include <boost/indirect_reference.hpp> #include <boost/indirect_reference.hpp>
#include <boost/next_prior.hpp> #include <boost/next_prior.hpp>
#include <boost/pointee.hpp> #include <boost/pointee.hpp>
#include <boost/shared_container_iterator.hpp>
#include <boost/iterator/advance.hpp> #include <boost/iterator/advance.hpp>
#include <boost/iterator/counting_iterator.hpp> #include <boost/iterator/counting_iterator.hpp>
#include <boost/iterator/distance.hpp> #include <boost/iterator/distance.hpp>
@ -31,6 +30,7 @@
#include <boost/iterator/new_iterator_tests.hpp> #include <boost/iterator/new_iterator_tests.hpp>
#include <boost/iterator/permutation_iterator.hpp> #include <boost/iterator/permutation_iterator.hpp>
#include <boost/iterator/reverse_iterator.hpp> #include <boost/iterator/reverse_iterator.hpp>
#include <boost/iterator/shared_container_iterator.hpp>
#include <boost/iterator/transform_iterator.hpp> #include <boost/iterator/transform_iterator.hpp>
#include <boost/iterator/zip_iterator.hpp> #include <boost/iterator/zip_iterator.hpp>