From 04c01c2c493255886e61fa75c2b5c9cf5c69f1f2 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Wed, 19 Feb 2014 01:12:04 +0100 Subject: [PATCH 01/10] Added perliminary version of algorithms move and move_backward, move_iterator, moved_range and adaptors::moved - NOT TESTED --- include/boost/range/adaptor/moved.hpp | 94 ++++++++++++++++ include/boost/range/algorithm/move.hpp | 44 ++++++++ .../boost/range/algorithm/move_backward.hpp | 46 ++++++++ include/boost/range/detail/move_iterator.hpp | 100 ++++++++++++++++++ 4 files changed, 284 insertions(+) create mode 100755 include/boost/range/adaptor/moved.hpp create mode 100644 include/boost/range/algorithm/move.hpp create mode 100644 include/boost/range/algorithm/move_backward.hpp create mode 100644 include/boost/range/detail/move_iterator.hpp diff --git a/include/boost/range/adaptor/moved.hpp b/include/boost/range/adaptor/moved.hpp new file mode 100755 index 000000000..c1c4aed7e --- /dev/null +++ b/include/boost/range/adaptor/moved.hpp @@ -0,0 +1,94 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen, Neil Groves 2006 - 2008. +// Copyright Adam Wulkiewicz 2014. +// +// 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_RANGE_ADAPTOR_MOVED_HPP +#define BOOST_RANGE_ADAPTOR_MOVED_HPP + +#include +#include + +#include +#include + +namespace boost { + +namespace range_detail { + +template< class R > +struct moved_range : + boost::iterator_range< +#ifdef BOOST_RANGE_MOVE_USE_BOOST_MOVE_ITERATOR + boost::move_iterator< +#else + range_detail::move_iterator< +#endif + BOOST_DEDUCED_TYPENAME range_iterator::type + > + > +{ +private: + typedef boost::iterator_range< +#ifdef BOOST_RANGE_MOVE_USE_BOOST_MOVE_ITERATOR + boost::move_iterator< +#else + range_detail::move_iterator< +#endif + BOOST_DEDUCED_TYPENAME range_iterator::type + > + > base; +public: + moved_range( R & r ) +#ifdef BOOST_RANGE_MOVE_USE_BOOST_MOVE_ITERATOR + : base( boost::make_move_iterator(boost::begin(r)), + boost::make_move_iterator(boost::end(r)) ) +#else + : base( range_detail::make_move_iterator(boost::begin(r)), + range_detail::make_move_iterator(boost::end(r)) ) +#endif + { } +}; + +struct move_forwarder {}; + +template< class InputRange > +inline moved_range +operator|( InputRange & r, move_forwarder ) +{ + return moved_range( r ); +} + +} // namespace range_detail + +// Unusual use of 'using' is intended to bring filter_range into the boost namespace +// while leaving the mechanics of the '|' operator in range_detail and maintain +// argument dependent lookup. +// filter_range logically needs to be in the boost namespace to allow user of +// the library to define the return type for filter() +using range_detail::moved_range; + +namespace adaptors { + +namespace +{ + const range_detail::move_forwarder moved = + range_detail::move_forwarder(); +} + +template +inline moved_range +move(InputRange & rng) +{ + return moved_range(rng); +} + +} // namespace adaptors + +} // namespace boost + +#endif // BOOST_RANGE_ADAPTOR_MOVED_HPP diff --git a/include/boost/range/algorithm/move.hpp b/include/boost/range/algorithm/move.hpp new file mode 100644 index 000000000..8a768dcad --- /dev/null +++ b/include/boost/range/algorithm/move.hpp @@ -0,0 +1,44 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. +// Copyright Adam Wulkiewicz 2014. +// +// 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_RANGE_ALGORITHM_MOVE_HPP +#define BOOST_RANGE_ALGORITHM_MOVE_HPP + +#include +#include +#include +#include +//#include + +#include + +namespace boost { + +namespace range { + +/// \brief template function move +/// +/// range-based version of the C++11 move std algorithm +/// +/// \pre SinglePassRange is a model of the SinglePassRangeConcept +/// \pre OutputIterator is a model of the OutputIteratorConcept +template< class SinglePassRange, class OutputIterator > +inline OutputIterator move(SinglePassRange & rng, OutputIterator out) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return ::boost::move(::boost::begin(rng), ::boost::end(rng), out); +} + +} // namespace range + +using range::move; + +} // namespace boost + +#endif // BOOST_RANGE_ALGORITHM_MOVE_HPP diff --git a/include/boost/range/algorithm/move_backward.hpp b/include/boost/range/algorithm/move_backward.hpp new file mode 100644 index 000000000..0988f8dd7 --- /dev/null +++ b/include/boost/range/algorithm/move_backward.hpp @@ -0,0 +1,46 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. +// Copyright Adam Wulkiewicz 2014. +// +// 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_RANGE_ALGORITHM_MOVE_BACKWARD_HPP +#define BOOST_RANGE_ALGORITHM_MOVE_BACKWARD_HPP + +#include +#include +#include +#include + +#include + +namespace boost { + +namespace range { + +/// \brief template function copy_backward +/// +/// range-based version of the C++11 move_backwards std algorithm +/// +/// \pre BidirectionalRange is a model of the BidirectionalRangeConcept +/// \pre BidirectionalTraversalWriteableIterator is a model of the BidirectionalIteratorConcept +/// \pre BidirectionalTraversalWriteableIterator is a model of the WriteableIteratorConcept +template< class BidirectionalRange, class BidirectionalTraversalWriteableIterator > +inline BidirectionalTraversalWriteableIterator +move_backward(BidirectionalRange & rng, + BidirectionalTraversalWriteableIterator out) +{ + BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); + return ::boost::move_backward(::boost::begin(rng), ::boost::end(rng), out); +} + +} // namespace range + +using range::copy_backward; + +} // namespace boost + +#endif // BOOST_RANGE_ALGORITHM_MOVE_BACKWARD_HPP diff --git a/include/boost/range/detail/move_iterator.hpp b/include/boost/range/detail/move_iterator.hpp new file mode 100644 index 000000000..027c9e2ce --- /dev/null +++ b/include/boost/range/detail/move_iterator.hpp @@ -0,0 +1,100 @@ +// Boost.Range library +// +// (C) Copyright Ion Gaztanaga 2012 +// (C) Copyright Adam Wulkiewicz 2014 +// +// 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_RANGE_DETAIL_MOVE_ITERATOR_HPP +#define BOOST_RANGE_DETAIL_MOVE_ITERATOR_HPP + +#include + +namespace boost { + +namespace range_detail { + +template +class move_iterator +{ +public: + typedef typename std::input_iterator_tag iterator_category; + + typedef It iterator_type; + typedef typename std::iterator_traits::value_type value_type; + typedef It pointer; + typedef typename std::iterator_traits::difference_type difference_type; + + #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + typedef value_type && reference; + #else + typedef typename ::boost::move_detail::if_ + < ::boost::has_move_emulation_enabled + , ::boost::rv& + , value_type & >::type reference; + #endif + + move_iterator() + {} + + explicit move_iterator(It i) + : m_it(i) + {} + + template + move_iterator(const move_iterator& u) + : m_it(u.base()) + {} + + iterator_type base() const + { return m_it; } + + reference operator*() const + { + #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES) + return *m_it; + #else + return ::boost::move(*m_it); + #endif + } + + pointer operator->() const + { return m_it; } + + move_iterator& operator++() + { ++m_it; return *this; } + + move_iterator operator++(int) + { move_iterator tmp(*this); ++(*this); return tmp; } + + friend bool operator==(const move_iterator& x, const move_iterator& y) + { return x.base() == y.base(); } + + friend bool operator!=(const move_iterator& x, const move_iterator& y) + { return x.base() != y.base(); } + +private: + It m_it; +}; + +template +inline move_iterator make_move_iterator(const It &it) +{ return move_iterator(it); } + +} // namespace range_detail + +namespace move_detail { + +template +struct is_move_iterator< ::boost::range::detail::move_iterator > + : public ::boost::move_detail::integral_constant +{ +}; + +} // namespace move_detail + +} //namespace boost + +#endif //#ifndef BOOST_RANGE_DETAIL_MOVE_ITERATOR_HPP From d5d5e0b76fe97d74a0f59c96bed54407ef1e0a4d Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Wed, 19 Feb 2014 15:05:05 +0100 Subject: [PATCH 02/10] added missing versions for const Ranges of moving algorithms and adaptors --- include/boost/range/adaptor/moved.hpp | 14 ++++++++++++++ include/boost/range/algorithm/move.hpp | 15 ++++++++++++++- .../boost/range/algorithm/move_backward.hpp | 18 +++++++++++++++++- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/include/boost/range/adaptor/moved.hpp b/include/boost/range/adaptor/moved.hpp index c1c4aed7e..8bcb15396 100755 --- a/include/boost/range/adaptor/moved.hpp +++ b/include/boost/range/adaptor/moved.hpp @@ -63,6 +63,13 @@ operator|( InputRange & r, move_forwarder ) return moved_range( r ); } +template< class InputRange > +inline moved_range +operator|( InputRange const& r, move_forwarder ) +{ + return moved_range( r ); +} + } // namespace range_detail // Unusual use of 'using' is intended to bring filter_range into the boost namespace @@ -87,6 +94,13 @@ move(InputRange & rng) return moved_range(rng); } +template +inline moved_range +move(InputRange const& rng) +{ + return moved_range(rng); +} + } // namespace adaptors } // namespace boost diff --git a/include/boost/range/algorithm/move.hpp b/include/boost/range/algorithm/move.hpp index 8a768dcad..b89e63efb 100644 --- a/include/boost/range/algorithm/move.hpp +++ b/include/boost/range/algorithm/move.hpp @@ -24,7 +24,7 @@ namespace range { /// \brief template function move /// -/// range-based version of the C++11 move std algorithm +/// range-based version of the move std algorithm /// /// \pre SinglePassRange is a model of the SinglePassRangeConcept /// \pre OutputIterator is a model of the OutputIteratorConcept @@ -35,6 +35,19 @@ inline OutputIterator move(SinglePassRange & rng, OutputIterator out) return ::boost::move(::boost::begin(rng), ::boost::end(rng), out); } +/// \brief template function move +/// +/// range-based version of the move std algorithm +/// +/// \pre SinglePassRange is a model of the SinglePassRangeConcept +/// \pre OutputIterator is a model of the OutputIteratorConcept +template< class SinglePassRange, class OutputIterator > +inline OutputIterator move(SinglePassRange const& rng, OutputIterator out) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return ::boost::move(::boost::begin(rng), ::boost::end(rng), out); +} + } // namespace range using range::move; diff --git a/include/boost/range/algorithm/move_backward.hpp b/include/boost/range/algorithm/move_backward.hpp index 0988f8dd7..c8aab6730 100644 --- a/include/boost/range/algorithm/move_backward.hpp +++ b/include/boost/range/algorithm/move_backward.hpp @@ -23,7 +23,7 @@ namespace range { /// \brief template function copy_backward /// -/// range-based version of the C++11 move_backwards std algorithm +/// range-based version of the move_backwards std algorithm /// /// \pre BidirectionalRange is a model of the BidirectionalRangeConcept /// \pre BidirectionalTraversalWriteableIterator is a model of the BidirectionalIteratorConcept @@ -37,6 +37,22 @@ move_backward(BidirectionalRange & rng, return ::boost::move_backward(::boost::begin(rng), ::boost::end(rng), out); } +/// \brief template function copy_backward +/// +/// range-based version of the move_backwards std algorithm +/// +/// \pre BidirectionalRange is a model of the BidirectionalRangeConcept +/// \pre BidirectionalTraversalWriteableIterator is a model of the BidirectionalIteratorConcept +/// \pre BidirectionalTraversalWriteableIterator is a model of the WriteableIteratorConcept +template< class BidirectionalRange, class BidirectionalTraversalWriteableIterator > +inline BidirectionalTraversalWriteableIterator +move_backward(BidirectionalRange const& rng, + BidirectionalTraversalWriteableIterator out) +{ + BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); + return ::boost::move_backward(::boost::begin(rng), ::boost::end(rng), out); +} + } // namespace range using range::copy_backward; From 3a9da0e1f2761a2c1fcdbcc5f1d92c82ed2f2c47 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Thu, 20 Feb 2014 01:07:54 +0100 Subject: [PATCH 03/10] boost::move_iterator used in moved_range --- include/boost/range/adaptor/moved.hpp | 14 --- include/boost/range/detail/move_iterator.hpp | 100 ------------------- 2 files changed, 114 deletions(-) delete mode 100644 include/boost/range/detail/move_iterator.hpp diff --git a/include/boost/range/adaptor/moved.hpp b/include/boost/range/adaptor/moved.hpp index 8bcb15396..f87901764 100755 --- a/include/boost/range/adaptor/moved.hpp +++ b/include/boost/range/adaptor/moved.hpp @@ -13,7 +13,6 @@ #include #include -#include #include namespace boost { @@ -23,34 +22,21 @@ namespace range_detail { template< class R > struct moved_range : boost::iterator_range< -#ifdef BOOST_RANGE_MOVE_USE_BOOST_MOVE_ITERATOR boost::move_iterator< -#else - range_detail::move_iterator< -#endif BOOST_DEDUCED_TYPENAME range_iterator::type > > { private: typedef boost::iterator_range< -#ifdef BOOST_RANGE_MOVE_USE_BOOST_MOVE_ITERATOR boost::move_iterator< -#else - range_detail::move_iterator< -#endif BOOST_DEDUCED_TYPENAME range_iterator::type > > base; public: moved_range( R & r ) -#ifdef BOOST_RANGE_MOVE_USE_BOOST_MOVE_ITERATOR : base( boost::make_move_iterator(boost::begin(r)), boost::make_move_iterator(boost::end(r)) ) -#else - : base( range_detail::make_move_iterator(boost::begin(r)), - range_detail::make_move_iterator(boost::end(r)) ) -#endif { } }; diff --git a/include/boost/range/detail/move_iterator.hpp b/include/boost/range/detail/move_iterator.hpp deleted file mode 100644 index 027c9e2ce..000000000 --- a/include/boost/range/detail/move_iterator.hpp +++ /dev/null @@ -1,100 +0,0 @@ -// Boost.Range library -// -// (C) Copyright Ion Gaztanaga 2012 -// (C) Copyright Adam Wulkiewicz 2014 -// -// 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_RANGE_DETAIL_MOVE_ITERATOR_HPP -#define BOOST_RANGE_DETAIL_MOVE_ITERATOR_HPP - -#include - -namespace boost { - -namespace range_detail { - -template -class move_iterator -{ -public: - typedef typename std::input_iterator_tag iterator_category; - - typedef It iterator_type; - typedef typename std::iterator_traits::value_type value_type; - typedef It pointer; - typedef typename std::iterator_traits::difference_type difference_type; - - #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - typedef value_type && reference; - #else - typedef typename ::boost::move_detail::if_ - < ::boost::has_move_emulation_enabled - , ::boost::rv& - , value_type & >::type reference; - #endif - - move_iterator() - {} - - explicit move_iterator(It i) - : m_it(i) - {} - - template - move_iterator(const move_iterator& u) - : m_it(u.base()) - {} - - iterator_type base() const - { return m_it; } - - reference operator*() const - { - #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES) - return *m_it; - #else - return ::boost::move(*m_it); - #endif - } - - pointer operator->() const - { return m_it; } - - move_iterator& operator++() - { ++m_it; return *this; } - - move_iterator operator++(int) - { move_iterator tmp(*this); ++(*this); return tmp; } - - friend bool operator==(const move_iterator& x, const move_iterator& y) - { return x.base() == y.base(); } - - friend bool operator!=(const move_iterator& x, const move_iterator& y) - { return x.base() != y.base(); } - -private: - It m_it; -}; - -template -inline move_iterator make_move_iterator(const It &it) -{ return move_iterator(it); } - -} // namespace range_detail - -namespace move_detail { - -template -struct is_move_iterator< ::boost::range::detail::move_iterator > - : public ::boost::move_detail::integral_constant -{ -}; - -} // namespace move_detail - -} //namespace boost - -#endif //#ifndef BOOST_RANGE_DETAIL_MOVE_ITERATOR_HPP From fd985780483ae178b6b57e7fa4e57abd4162245f Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Thu, 20 Feb 2014 02:09:08 +0100 Subject: [PATCH 04/10] added move and move_backward tests and fixed some errors --- include/boost/range/algorithm/move.hpp | 2 +- .../boost/range/algorithm/move_backward.hpp | 4 +- test/algorithm_test/move.cpp | 114 ++++++++++++++++++ test/algorithm_test/move_backward.cpp | 114 ++++++++++++++++++ test/copymovable.hpp | 64 ++++++++++ 5 files changed, 295 insertions(+), 3 deletions(-) create mode 100644 test/algorithm_test/move.cpp create mode 100644 test/algorithm_test/move_backward.cpp create mode 100644 test/copymovable.hpp diff --git a/include/boost/range/algorithm/move.hpp b/include/boost/range/algorithm/move.hpp index b89e63efb..50911e2f3 100644 --- a/include/boost/range/algorithm/move.hpp +++ b/include/boost/range/algorithm/move.hpp @@ -16,7 +16,7 @@ #include //#include -#include +#include namespace boost { diff --git a/include/boost/range/algorithm/move_backward.hpp b/include/boost/range/algorithm/move_backward.hpp index c8aab6730..644d82639 100644 --- a/include/boost/range/algorithm/move_backward.hpp +++ b/include/boost/range/algorithm/move_backward.hpp @@ -15,7 +15,7 @@ #include #include -#include +#include namespace boost { @@ -55,7 +55,7 @@ move_backward(BidirectionalRange const& rng, } // namespace range -using range::copy_backward; +using range::move_backward; } // namespace boost diff --git a/test/algorithm_test/move.cpp b/test/algorithm_test/move.cpp new file mode 100644 index 000000000..422a95bf1 --- /dev/null +++ b/test/algorithm_test/move.cpp @@ -0,0 +1,114 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. +// Copyright Adam Wulkiewicz 2014. +// +// 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../copymovable.hpp" + +namespace boost +{ + namespace + { + template + bool check_moved(It first, It last, bool expected) + { + for ( ; first != last ; ++first ) + if ( first->moved() != expected ) + return false; + return true; + } + + template< class Container > + void test_move_impl(bool expect_move) + { + typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; + + std::vector input; + input.push_back(copy_movable(1)); + input.push_back(copy_movable(2)); + input.push_back(copy_movable(3)); + + { + Container source(input.begin(), input.end()); + + BOOST_CHECK(check_moved(source.begin(), source.end(), false)); + + std::vector target; + target.resize(source.size()); + + typedef BOOST_DEDUCED_TYPENAME range_iterator< std::vector >::type iterator_t; + + iterator_t it = boost::move(source, target.begin()); + + BOOST_CHECK(check_moved(source.begin(), source.end(), expect_move)); + + BOOST_CHECK( it == target.end() ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + target.begin(), target.end(), + input.begin(), input.end() + ); + } + + { + Container source(input.begin(), input.end()); + + BOOST_CHECK(check_moved(source.begin(), source.end(), false)); + + std::vector target; + target.resize(source.size()); + + typedef BOOST_DEDUCED_TYPENAME range_iterator< std::vector >::type iterator_t; + + iterator_t it = boost::move(boost::make_iterator_range(source), target.begin()); + + BOOST_CHECK(check_moved(source.begin(), source.end(), expect_move)); + + BOOST_CHECK( it == target.end() ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + target.begin(), target.end(), + input.begin(), input.end() + ); + } + } + + void test_move() + { + test_move_impl< std::vector >(true); + test_move_impl< std::list >(true); + test_move_impl< std::set >(false); + test_move_impl< std::multiset >(false); + } + } +} + + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.move" ); + + test->add( BOOST_TEST_CASE( &boost::test_move ) ); + + return test; +} diff --git a/test/algorithm_test/move_backward.cpp b/test/algorithm_test/move_backward.cpp new file mode 100644 index 000000000..ee33a0a7a --- /dev/null +++ b/test/algorithm_test/move_backward.cpp @@ -0,0 +1,114 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. +// Copyright Adam Wulkiewicz 2014. +// +// 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../copymovable.hpp" + +namespace boost +{ + namespace + { + template + bool check_moved(It first, It last, bool expected) + { + for ( ; first != last ; ++first ) + if ( first->moved() != expected ) + return false; + return true; + } + + template< class Container > + void test_move_backward_impl(bool expect_move) + { + typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; + + std::vector input; + input.push_back(copy_movable(1)); + input.push_back(copy_movable(2)); + input.push_back(copy_movable(3)); + + { + Container source(input.begin(), input.end()); + + BOOST_CHECK(check_moved(source.begin(), source.end(), false)); + + std::vector target; + target.resize(source.size()); + + typedef BOOST_DEDUCED_TYPENAME range_iterator< std::vector >::type iterator_t; + + iterator_t it = boost::move_backward(source, target.end()); + + BOOST_CHECK(check_moved(source.begin(), source.end(), expect_move)); + + BOOST_CHECK( it == target.begin() ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + target.begin(), target.end(), + input.begin(), input.end() + ); + } + + { + Container source(input.begin(), input.end()); + + BOOST_CHECK(check_moved(source.begin(), source.end(), false)); + + std::vector target; + target.resize(source.size()); + + typedef BOOST_DEDUCED_TYPENAME range_iterator< std::vector >::type iterator_t; + + iterator_t it = boost::move_backward(boost::make_iterator_range(source), target.end()); + + BOOST_CHECK(check_moved(source.begin(), source.end(), expect_move)); + + BOOST_CHECK( it == target.begin() ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + target.begin(), target.end(), + input.begin(), input.end() + ); + } + } + + void test_move_backward() + { + test_move_backward_impl< std::vector >(true); + test_move_backward_impl< std::list >(true); + test_move_backward_impl< std::set >(false); + test_move_backward_impl< std::multiset >(false); + } + } +} + + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.move_backward" ); + + test->add( BOOST_TEST_CASE( &boost::test_move_backward ) ); + + return test; +} diff --git a/test/copymovable.hpp b/test/copymovable.hpp new file mode 100644 index 000000000..40ff451d7 --- /dev/null +++ b/test/copymovable.hpp @@ -0,0 +1,64 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009. +// (C) Copyright Adam Wulkiewicz 2014. +// +// 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_MOVE_TEST_COPYMOVABLE_HPP +#define BOOST_MOVE_TEST_COPYMOVABLE_HPP + +#include + +//[movable_definition +//header file "copy_movable.hpp" +#include + +#include + +//A copy_movable class +class copy_movable +{ + BOOST_COPYABLE_AND_MOVABLE(copy_movable) + int value_; + + public: + copy_movable(int v = 1) : value_(v) { BOOST_ASSERT(v > 0); } + + //Move constructor and assignment + copy_movable(BOOST_RV_REF(copy_movable) m) + { value_ = m.value_; m.value_ = 0; } + + copy_movable(const copy_movable & m) + { value_ = m.value_; } + + copy_movable & operator=(BOOST_RV_REF(copy_movable) m) + { value_ = m.value_; m.value_ = 0; return *this; } + + copy_movable & operator=(BOOST_COPY_ASSIGN_REF(copy_movable) m) + { value_ = m.value_; return *this; } + + bool moved() const //Observer + { return value_ == 0; } + + friend bool operator==(copy_movable const& l, copy_movable const& r) + { return l.value_ == r.value_; } + + friend bool operator!=(copy_movable const& l, copy_movable const& r) + { return l.value_ != r.value_; } + + friend bool operator<(copy_movable const& l, copy_movable const& r) + { return l.value_ < r.value_; } + + friend std::ostream & operator<<(std::ostream & os, copy_movable const& r) + { return os << (r.moved() ? " moved" : " not moved"); } +}; + +//] + +#include + +#endif //BOOST_MOVE_TEST_COPYMOVABLE_HPP From 8849b851bfdf63cd1e065633f5835ade44acaa8f Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Thu, 20 Feb 2014 02:13:19 +0100 Subject: [PATCH 05/10] fixed errors in copy_backward() test --- test/algorithm_test/copy_backward.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/test/algorithm_test/copy_backward.cpp b/test/algorithm_test/copy_backward.cpp index 3fd5679d5..d3cd4ec62 100644 --- a/test/algorithm_test/copy_backward.cpp +++ b/test/algorithm_test/copy_backward.cpp @@ -27,22 +27,28 @@ namespace boost template< class Container > void test_copy_backward_impl() { - Container source; + std::vector input; + input.push_back(1); + input.push_back(2); + input.push_back(3); + + Container source(input.begin(), input.end()); typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; std::vector target; target.resize(source.size()); typedef BOOST_DEDUCED_TYPENAME range_iterator< std::vector >::type iterator_t; - iterator_t it = boost::copy_backward(source, target.begin()); + iterator_t it = boost::copy_backward(source, target.end()); - BOOST_CHECK( it == target.end() ); - BOOST_CHECK_EQUAL_COLLECTIONS( target.begin(), target.end(), - source.rbegin(), source.rend() ); + BOOST_CHECK( it == target.begin() ); + BOOST_CHECK_EQUAL_COLLECTIONS( + target.begin(), target.end(), + source.begin(), source.end() ); - BOOST_CHECK( it == boost::copy_backward(boost::make_iterator_range(source), target.begin()) ); + BOOST_CHECK( it == boost::copy_backward(boost::make_iterator_range(source), target.end()) ); BOOST_CHECK_EQUAL_COLLECTIONS( target.begin(), target.end(), - source.rbegin(), source.rend() ); + source.begin(), source.end() ); } void test_copy_backward() From 18b36983886d25c35e183926adf89de13b6795f0 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Thu, 20 Feb 2014 02:14:18 +0100 Subject: [PATCH 06/10] added missing copyright info --- test/algorithm_test/copy_backward.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/algorithm_test/copy_backward.cpp b/test/algorithm_test/copy_backward.cpp index d3cd4ec62..0720c954c 100644 --- a/test/algorithm_test/copy_backward.cpp +++ b/test/algorithm_test/copy_backward.cpp @@ -1,9 +1,11 @@ // Boost.Range library // -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to 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) +// Copyright Neil Groves 2009. +// Copyright Adam Wulkiewicz 2014. +// +// 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) // // // For more information, see http://www.boost.org/libs/range/ From a9acd6652bbb59d0921d89038df069b4430df7c6 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Thu, 20 Feb 2014 02:38:52 +0100 Subject: [PATCH 07/10] added test for adaptor moved --- include/boost/range/adaptor/moved.hpp | 2 +- test/Jamfile.v2 | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/boost/range/adaptor/moved.hpp b/include/boost/range/adaptor/moved.hpp index f87901764..735cbe862 100755 --- a/include/boost/range/adaptor/moved.hpp +++ b/include/boost/range/adaptor/moved.hpp @@ -13,7 +13,7 @@ #include #include -#include +#include namespace boost { diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index bcaa772a1..88c27ffc2 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -38,6 +38,7 @@ test-suite range : [ range-test adaptor_test/indexed ] [ range-test adaptor_test/indirected ] [ range-test adaptor_test/map ] + [ range-test adaptor_test/moved ] [ range-test adaptor_test/replaced ] [ range-test adaptor_test/replaced_if ] [ range-test adaptor_test/reversed ] @@ -88,6 +89,8 @@ test-suite range : [ range-test algorithm_test/merge ] [ range-test algorithm_test/min_element ] [ range-test algorithm_test/mismatch ] + [ range-test algorithm_test/move ] + [ range-test algorithm_test/move_backward ] [ range-test algorithm_test/next_permutation ] [ range-test algorithm_test/nth_element ] [ range-test algorithm_test/partial_sort ] From f9b632f411fea5bd419275cc0e64fcde35f890f7 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Thu, 20 Feb 2014 02:39:48 +0100 Subject: [PATCH 08/10] added missing file --- test/adaptor_test/moved.cpp | 105 ++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 test/adaptor_test/moved.cpp diff --git a/test/adaptor_test/moved.cpp b/test/adaptor_test/moved.cpp new file mode 100644 index 000000000..ae992fb6f --- /dev/null +++ b/test/adaptor_test/moved.cpp @@ -0,0 +1,105 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. +// Copyright Adam Wulkiewicz 2014. +// +// 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "../copymovable.hpp" + +namespace boost +{ + template + bool check_moved(It first, It last, bool expected) + { + for ( ; first != last ; ++first ) + if ( first->moved() != expected ) + return false; + return true; + } + + template< class Container > + void moved_test_impl( Container& c, bool expect_move) + { + using namespace boost::adaptors; + + { + Container source = c; + check_moved(source.begin(), source.end(), false); + std::vector< copy_movable > test_result1; + boost::push_back(test_result1, source | moved); + check_moved(source.begin(), source.end(), expect_move); + + BOOST_CHECK_EQUAL_COLLECTIONS( c.begin(), c.end(), + test_result1.begin(), test_result1.end() ); + } + + { + Container source = c; + check_moved(source.begin(), source.end(), false); + std::vector< copy_movable > test_result2; + boost::push_back(test_result2, adaptors::move(c)); + check_moved(source.begin(), source.end(), expect_move); + + BOOST_CHECK_EQUAL_COLLECTIONS( c.begin(), c.end(), + test_result2.begin(), test_result2.end() ); + } + } + + template< class Container > + void moved_test_impl(bool expect_move) + { + using namespace boost::assign; + + Container c; + + // Test empty + moved_test_impl(c, expect_move); + + // Test one + c += copy_movable(1); + moved_test_impl(c, expect_move); + + // Test many + c += copy_movable(1),copy_movable(2),copy_movable(3); + moved_test_impl(c, expect_move); + } + + void moved_test() + { + moved_test_impl< std::vector< copy_movable > >(true); + moved_test_impl< std::list< copy_movable > >(true); + moved_test_impl< std::set< copy_movable > >(false); + moved_test_impl< std::multiset< copy_movable > >(false); + } +} + + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.moved" ); + + test->add( BOOST_TEST_CASE( &boost::moved_test ) ); + + return test; +} From 31f2ffd91e1f1153621081062869704a8b13b5a8 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Thu, 20 Feb 2014 03:05:26 +0100 Subject: [PATCH 09/10] fixed errors in move adaptor test --- test/adaptor_test/moved.cpp | 34 +++++++++++++++++----------------- test/copymovable.hpp | 2 +- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/test/adaptor_test/moved.cpp b/test/adaptor_test/moved.cpp index ae992fb6f..357f53027 100644 --- a/test/adaptor_test/moved.cpp +++ b/test/adaptor_test/moved.cpp @@ -20,7 +20,6 @@ #include #include -#include #include #include "../copymovable.hpp" @@ -37,27 +36,27 @@ namespace boost } template< class Container > - void moved_test_impl( Container& c, bool expect_move) + void moved_test_impl( Container& c) { using namespace boost::adaptors; { - Container source = c; + Container source(c.begin(), c.end()); check_moved(source.begin(), source.end(), false); std::vector< copy_movable > test_result1; boost::push_back(test_result1, source | moved); - check_moved(source.begin(), source.end(), expect_move); + check_moved(source.begin(), source.end(), true); BOOST_CHECK_EQUAL_COLLECTIONS( c.begin(), c.end(), test_result1.begin(), test_result1.end() ); } { - Container source = c; + Container source(c.begin(), c.end()); check_moved(source.begin(), source.end(), false); std::vector< copy_movable > test_result2; - boost::push_back(test_result2, adaptors::move(c)); - check_moved(source.begin(), source.end(), expect_move); + boost::push_back(test_result2, adaptors::move(source)); + check_moved(source.begin(), source.end(), true); BOOST_CHECK_EQUAL_COLLECTIONS( c.begin(), c.end(), test_result2.begin(), test_result2.end() ); @@ -65,30 +64,31 @@ namespace boost } template< class Container > - void moved_test_impl(bool expect_move) + void moved_test_impl() { using namespace boost::assign; Container c; // Test empty - moved_test_impl(c, expect_move); + moved_test_impl(c); // Test one - c += copy_movable(1); - moved_test_impl(c, expect_move); + copy_movable c1(1); + c += c1; + moved_test_impl(c); // Test many - c += copy_movable(1),copy_movable(2),copy_movable(3); - moved_test_impl(c, expect_move); + copy_movable c2(2); + copy_movable c3(3); + c += c2, c3; + moved_test_impl(c); } void moved_test() { - moved_test_impl< std::vector< copy_movable > >(true); - moved_test_impl< std::list< copy_movable > >(true); - moved_test_impl< std::set< copy_movable > >(false); - moved_test_impl< std::multiset< copy_movable > >(false); + moved_test_impl< std::vector< copy_movable > >(); + moved_test_impl< std::list< copy_movable > >(); } } diff --git a/test/copymovable.hpp b/test/copymovable.hpp index 40ff451d7..215918689 100644 --- a/test/copymovable.hpp +++ b/test/copymovable.hpp @@ -54,7 +54,7 @@ class copy_movable { return l.value_ < r.value_; } friend std::ostream & operator<<(std::ostream & os, copy_movable const& r) - { return os << (r.moved() ? " moved" : " not moved"); } + { return os << r.value_; } }; //] From ab385787780d66f8b6f0e2abe606746e615869ad Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Thu, 20 Feb 2014 21:50:58 +0100 Subject: [PATCH 10/10] added README --- README.md | 13 + doc/logo/logo.svg | 9025 +++++++++++++++++++++++++++++++++++++++++ doc/logo/logo_bkg.png | Bin 0 -> 10116 bytes 3 files changed, 9038 insertions(+) create mode 100644 README.md create mode 100644 doc/logo/logo.svg create mode 100644 doc/logo/logo_bkg.png diff --git a/README.md b/README.md new file mode 100644 index 000000000..87f7923ad --- /dev/null +++ b/README.md @@ -0,0 +1,13 @@ +#![Boost.Range](doc/logo/logo_bkg.png) + +Boost.Range, part of the [Boost C++ Libraries](http://github.com/boostorg), a collection of concepts and utilities, range-based algorithms, as well as range adaptors that allow for efficient and expressive code. + +### Directories + +* **doc** - QuickBook documentation sources +* **include** - the sourcecode of Boost.Range +* **test** - Boost.Range unit tests + +### More information + +* [Documentation](http://boost.org/libs/range) diff --git a/doc/logo/logo.svg b/doc/logo/logo.svg new file mode 100644 index 000000000..abae4ebec --- /dev/null +++ b/doc/logo/logo.svg @@ -0,0 +1,9025 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + RANGE + + + + boost + + + [..) + + + + + + + + + + + + + + + + + + + + + + + + + + + Range + + + + boost + + + [..) + + diff --git a/doc/logo/logo_bkg.png b/doc/logo/logo_bkg.png new file mode 100644 index 0000000000000000000000000000000000000000..cead7c1e56844baa7e2dc0713dad0fddaf4bc84c GIT binary patch literal 10116 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 mUP=C%ge-MINlG$*