diff --git a/CMakeLists.txt b/CMakeLists.txt index 0706aeb..d11edf8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,6 @@ target_link_libraries(boost_iterator Boost::fusion Boost::mpl Boost::optional - Boost::smart_ptr Boost::type_traits Boost::utility ) diff --git a/build.jam b/build.jam index ecc77c7..5cdfb93 100644 --- a/build.jam +++ b/build.jam @@ -14,7 +14,6 @@ constant boost_dependencies : /boost/fusion//boost_fusion /boost/mpl//boost_mpl /boost/optional//boost_optional - /boost/smart_ptr//boost_smart_ptr /boost/type_traits//boost_type_traits /boost/utility//boost_utility ; diff --git a/doc/index.html b/doc/index.html index 65973b4..ece73ae 100644 --- a/doc/index.html +++ b/doc/index.html @@ -140,7 +140,7 @@ sequence, rearranged according to some sequence of integer indices. bidirectional sequence in reverse. Corrects many of the shortcomings of C++98's std::reverse_iterator.
  • shared_container_iterator: an iterator over elements of a container whose -lifetime is maintained by a shared_ptr stored in the iterator.
  • +lifetime is maintained by a shared_ptr stored in the iterator.
  • transform_iterator (PDF): an iterator over elements which are the result of applying some functional transformation to the elements of an underlying sequence. This component also replaces the old diff --git a/doc/quickbook/shared_container_iterator.qbk b/doc/quickbook/shared_container_iterator.qbk index b87678a..8e6463a 100644 --- a/doc/quickbook/shared_container_iterator.qbk +++ b/doc/quickbook/shared_container_iterator.qbk @@ -1,6 +1,6 @@ [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 of a container to the lifetime of its iterators. In other words, the @@ -24,9 +24,22 @@ iterator. [h2 Synopsis] namespace boost { + namespace iterators { template class shared_container_iterator; + template + shared_container_iterator + make_shared_container_iterator(typename Container::iterator base, + std::shared_ptr const& container); + + std::pair< + typename shared_container_iterator, + typename shared_container_iterator + > + make_shared_container_range(std::shared_ptr const& container); + + // Backward compatibility with boost::shared_ptr template shared_container_iterator make_shared_container_iterator(typename Container::iterator base, @@ -38,6 +51,15 @@ iterator. > make_shared_container_range(boost::shared_ptr 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] @@ -57,18 +79,17 @@ the underlying vector and thereby extend the container's lifetime. [example_link shared_iterator_example1.cpp..`shared_iterator_example1.cpp`]: - #include "shared_container_iterator.hpp" - #include "boost/shared_ptr.hpp" + #include #include #include #include + #include - typedef boost::shared_container_iterator< std::vector > iterator; + using iterator = boost::iterators::shared_container_iterator< std::vector >; - void set_range(iterator& i, iterator& end) { - - boost::shared_ptr< std::vector > ints(new std::vector()); + void set_range(iterator& i, iterator& end) { + std::shared_ptr< std::vector > ints(new std::vector()); ints->push_back(0); 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(5); - i = iterator(ints->begin(),ints); - end = iterator(ints->end(),ints); + i = iterator(ints->begin(), ints); + end = iterator(ints->end(), ints); } int main() { + iterator i, end; - iterator i,end; + set_range(i, end); - set_range(i,end); - - std::copy(i,end,std::ostream_iterator(std::cout,",")); + std::copy(i, end, std::ostream_iterator(std::cout, ",")); std::cout.put('\n'); return 0; @@ -116,8 +136,12 @@ The `shared_container_iterator` type implements the member functions and operators required of the [@http://www.sgi.com/tech/stl/RandomAccessIterator.html Random Access 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 const& container) + + // Backward compatibility with boost::shared_ptr shared_container_iterator(Container::iterator const& it, boost::shared_ptr 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] + template + shared_container_iterator + make_shared_container_iterator(Container::iterator base, + std::shared_ptr const& container) + + // Backward compatibility with boost::shared_ptr template shared_container_iterator 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`]: - #include "shared_container_iterator.hpp" - #include "boost/shared_ptr.hpp" + #include #include #include #include #include + #include template - void print_range_nl (Iterator begin, Iterator end) { - typedef typename std::iterator_traits::value_type val; - std::copy(begin,end,std::ostream_iterator(std::cout,",")); + void print_range_nl(Iterator begin, Iterator end) { + using val = typename std::iterator_traits::value_type; + std::copy(begin, end, std::ostream_iterator(std::cout, ",")); std::cout.put('\n'); } - int main() { - - typedef boost::shared_ptr< std::vector > ints_t; + using ints_t = std::shared_ptr< std::vector >; { ints_t ints(new std::vector()); @@ -171,12 +199,10 @@ uses `make_shared_container_iterator()` to create the iterators. ints->push_back(4); ints->push_back(5); - print_range_nl(boost::make_shared_container_iterator(ints->begin(),ints), - boost::make_shared_container_iterator(ints->end(),ints)); + print_range_nl(boost::iterators::make_shared_container_iterator(ints->begin(), ints), + boost::iterators::make_shared_container_iterator(ints->end(), ints)); } - - 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] + template + std::pair< + shared_container_iterator, + shared_container_iterator + > + make_shared_container_range(std::shared_ptr const& container); + + // Backward compatibility with boost::shared_ptr template std::pair< shared_container_iterator, shared_container_iterator > make_shared_container_range(boost::shared_ptr 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), - make_shared_container_iterator(container->end(),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 functionally equivalent to this: + + std::make_pair(make_shared_container_iterator(container->begin(), container), + make_shared_container_iterator(container->end(), container)); [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`]: - #include "shared_container_iterator.hpp" - #include "boost/shared_ptr.hpp" - #include "boost/tuple/tuple.hpp" // for boost::tie - #include // for std::copy + #include + #include // for std::copy #include #include + #include + #include // for std::tie - typedef boost::shared_container_iterator< std::vector > iterator; + using iterator = boost::iterators::shared_container_iterator< std::vector >; - std::pair + std::pair return_range() { - boost::shared_ptr< std::vector > range(new std::vector()); + std::shared_ptr< std::vector > range(new std::vector()); range->push_back(0); range->push_back(1); range->push_back(2); range->push_back(3); range->push_back(4); range->push_back(5); - return boost::make_shared_container_range(range); + return boost::iterators::make_shared_container_range(range); } - int main() { - - iterator i,end; + std::tie(i, end) = return_range(); - boost::tie(i,end) = return_range(); - - std::copy(i,end,std::ostream_iterator(std::cout,",")); + std::copy(i, end, std::ostream_iterator(std::cout, ",")); std::cout.put('\n'); return 0; diff --git a/include/boost/iterator/shared_container_iterator.hpp b/include/boost/iterator/shared_container_iterator.hpp new file mode 100644 index 0000000..deffd05 --- /dev/null +++ b/include/boost/iterator/shared_container_iterator.hpp @@ -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 +#include +#include + +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_ diff --git a/include/boost/shared_container_iterator.hpp b/include/boost/shared_container_iterator.hpp index 8adcaf7..907b2bb 100644 --- a/include/boost/shared_container_iterator.hpp +++ b/include/boost/shared_container_iterator.hpp @@ -1,69 +1,14 @@ -// (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. +// (C) Copyright Andrey Semashev 2025. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_SHARED_CONTAINER_ITERATOR_HPP #define BOOST_SHARED_CONTAINER_ITERATOR_HPP -#include "boost/iterator_adaptors.hpp" -#include "boost/shared_ptr.hpp" -#include +// This is a deprecated header left for backward compatibility. +// Please use instead. -namespace boost { -namespace iterators { +#include -template -class shared_container_iterator : public iterator_adaptor< - shared_container_iterator, - typename Container::iterator> { - - typedef iterator_adaptor< - shared_container_iterator, - typename Container::iterator> super_t; - - typedef typename Container::iterator iterator_t; - typedef boost::shared_ptr 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 -inline shared_container_iterator -make_shared_container_iterator(typename Container::iterator iter, - boost::shared_ptr const& container) { - typedef shared_container_iterator iterator; - return iterator(iter,container); -} - - - -template -inline std::pair< - shared_container_iterator, - shared_container_iterator > -make_shared_container_range(boost::shared_ptr 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 +#endif // BOOST_SHARED_CONTAINER_ITERATOR_HPP diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index d89fb37..afd5dae 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -74,5 +74,5 @@ test-suite iterator [ compile adl_test.cpp : /boost/array//boost_array ] [ compile range_distance_compat_test.cpp : /boost/range//boost_range ] - [ run shared_iterator_test.cpp ] + [ run shared_iterator_test.cpp : : : /boost/smart_ptr//boost_smart_ptr ] ; diff --git a/test/shared_iterator_test.cpp b/test/shared_iterator_test.cpp index a943d30..70fbd2c 100644 --- a/test/shared_iterator_test.cpp +++ b/test/shared_iterator_test.cpp @@ -14,12 +14,14 @@ // -#include "boost/shared_container_iterator.hpp" -#include "boost/shared_ptr.hpp" +#include +#include #include #include +#include -struct resource { +struct resource +{ static int count; resource() { ++count; } resource(resource const&) { ++count; } @@ -27,20 +29,20 @@ struct resource { }; int resource::count = 0; -typedef std::vector resources_t; +typedef std::vector< resource > resources_t; typedef boost::shared_container_iterator< resources_t > iterator; - -void set_range(iterator& i, iterator& end) { - - boost::shared_ptr< resources_t > objs(new resources_t()); +template< typename SharedPtr > +void set_range(iterator& i, iterator& end) +{ + SharedPtr objs(new resources_t()); for (int j = 0; j != 6; ++j) objs->push_back(resource()); - i = iterator(objs->begin(),objs); - end = iterator(objs->end(),objs); + i = iterator(objs->begin(), objs); + end = iterator(objs->end(), objs); BOOST_TEST_EQ(resource::count, 6); } @@ -53,7 +55,18 @@ int main() { iterator i; { 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); diff --git a/test/test_cmake/main.cpp b/test/test_cmake/main.cpp index ea4f74d..aee9c10 100644 --- a/test/test_cmake/main.cpp +++ b/test/test_cmake/main.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -31,6 +30,7 @@ #include #include #include +#include #include #include