1 //  Copyright Neil Groves 2009. Use, modification and
2 //  distribution is subject to the Boost Software License, Version
3 //  1.0. (See accompanying file LICENSE_1_0.txt or copy at
4 //  http://www.boost.org/LICENSE_1_0.txt)
5 //
6 //
7 // For more information, see http://www.boost.org/libs/range/
8 //
9 #ifndef BOOST_RANGE_ALGORITHM_SWAP_RANGES_HPP_INCLUDED
10 #define BOOST_RANGE_ALGORITHM_SWAP_RANGES_HPP_INCLUDED
11 
12 #include <boost/assert.hpp>
13 #include <boost/concept_check.hpp>
14 #include <boost/iterator/iterator_categories.hpp>
15 #include <boost/range/begin.hpp>
16 #include <boost/range/end.hpp>
17 #include <boost/range/concepts.hpp>
18 #include <boost/range/iterator.hpp>
19 #include <algorithm>
20 
21 namespace boost
22 {
23     namespace range_detail
24     {
25         template<class Iterator1, class Iterator2>
swap_ranges_impl(Iterator1 it1,Iterator1 last1,Iterator2 it2,Iterator2 last2,single_pass_traversal_tag,single_pass_traversal_tag)26         void swap_ranges_impl(Iterator1 it1, Iterator1 last1,
27                               Iterator2 it2, Iterator2 last2,
28                               single_pass_traversal_tag,
29                               single_pass_traversal_tag)
30         {
31             ignore_unused_variable_warning(last2);
32             for (; it1 != last1; ++it1, ++it2)
33             {
34                 BOOST_ASSERT( it2 != last2 );
35                 std::iter_swap(it1, it2);
36             }
37         }
38 
39         template<class Iterator1, class Iterator2>
swap_ranges_impl(Iterator1 it1,Iterator1 last1,Iterator2 it2,Iterator2 last2,random_access_traversal_tag,random_access_traversal_tag)40         void swap_ranges_impl(Iterator1 it1, Iterator1 last1,
41                               Iterator2 it2, Iterator2 last2,
42                               random_access_traversal_tag,
43                               random_access_traversal_tag)
44         {
45             ignore_unused_variable_warning(last2);
46             BOOST_ASSERT( last2 - it2 >= last1 - it1 );
47             std::swap_ranges(it1, last1, it2);
48         }
49 
50         template<class Iterator1, class Iterator2>
swap_ranges_impl(Iterator1 first1,Iterator1 last1,Iterator2 first2,Iterator2 last2)51         void swap_ranges_impl(Iterator1 first1, Iterator1 last1,
52                               Iterator2 first2, Iterator2 last2)
53         {
54             swap_ranges_impl(first1, last1, first2, last2,
55                 BOOST_DEDUCED_TYPENAME iterator_traversal<Iterator1>::type(),
56                 BOOST_DEDUCED_TYPENAME iterator_traversal<Iterator2>::type());
57         }
58     } // namespace range_detail
59 
60     namespace range
61     {
62 
63 /// \brief template function swap_ranges
64 ///
65 /// range-based version of the swap_ranges std algorithm
66 ///
67 /// \pre SinglePassRange1 is a model of the SinglePassRangeConcept
68 /// \pre SinglePassRange2 is a model of the SinglePassRangeConcept
69 template< class SinglePassRange1, class SinglePassRange2 >
70 inline SinglePassRange2&
swap_ranges(SinglePassRange1 & range1,SinglePassRange2 & range2)71 swap_ranges(SinglePassRange1& range1, SinglePassRange2& range2)
72 {
73     BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept<SinglePassRange1>));
74     BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept<SinglePassRange2>));
75 
76     boost::range_detail::swap_ranges_impl(
77         boost::begin(range1), boost::end(range1),
78         boost::begin(range2), boost::end(range2));
79 
80     return range2;
81 }
82 
83 /// \overload
84 template< class SinglePassRange1, class SinglePassRange2 >
85 inline SinglePassRange2&
swap_ranges(const SinglePassRange1 & range1,SinglePassRange2 & range2)86 swap_ranges(const SinglePassRange1& range1, SinglePassRange2& range2)
87 {
88     BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept<const SinglePassRange1>));
89     BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept<SinglePassRange2>));
90 
91     boost::range_detail::swap_ranges_impl(
92         boost::begin(range1), boost::end(range1),
93         boost::begin(range2), boost::end(range2));
94 
95     return range2;
96 }
97 
98 /// \overload
99 template< class SinglePassRange1, class SinglePassRange2 >
100 inline const SinglePassRange2&
swap_ranges(SinglePassRange1 & range1,const SinglePassRange2 & range2)101 swap_ranges(SinglePassRange1& range1, const SinglePassRange2& range2)
102 {
103     BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept<SinglePassRange1>));
104     BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept<const SinglePassRange2>));
105 
106     boost::range_detail::swap_ranges_impl(
107         boost::begin(range1), boost::end(range1),
108         boost::begin(range2), boost::end(range2));
109 
110     return range2;
111 }
112 
113 /// \overload
114 template< class SinglePassRange1, class SinglePassRange2 >
115 inline const SinglePassRange2&
swap_ranges(const SinglePassRange1 & range1,const SinglePassRange2 & range2)116 swap_ranges(const SinglePassRange1& range1, const SinglePassRange2& range2)
117 {
118     BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept<const SinglePassRange1>));
119     BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept<const SinglePassRange2>));
120 
121     boost::range_detail::swap_ranges_impl(
122         boost::begin(range1), boost::end(range1),
123         boost::begin(range2), boost::end(range2));
124 
125     return range2;
126 }
127 
128     } // namespace range
129     using range::swap_ranges;
130 } // namespace boost
131 
132 #endif // include guard
133