1 /// \file
2 // Range v3 library
3 //
4 //  Copyright Eric Niebler 2013-present
5 //  Copyright Gonzalo Brito Gadeschi 2014
6 //
7 //  Use, modification and distribution is subject to the
8 //  Boost Software License, Version 1.0. (See accompanying
9 //  file LICENSE_1_0.txt or copy at
10 //  http://www.boost.org/LICENSE_1_0.txt)
11 //
12 // Project home: https://github.com/ericniebler/range-v3
13 //
14 // Implementation based on the code in libc++
15 //   http://http://libcxx.llvm.org/
16 
17 #ifndef RANGES_V3_ALGORITHM_UNIQUE_HPP
18 #define RANGES_V3_ALGORITHM_UNIQUE_HPP
19 
20 #include <range/v3/range_fwd.hpp>
21 
22 #include <range/v3/algorithm/adjacent_find.hpp>
23 #include <range/v3/functional/comparisons.hpp>
24 #include <range/v3/functional/identity.hpp>
25 #include <range/v3/functional/invoke.hpp>
26 #include <range/v3/iterator/operations.hpp>
27 #include <range/v3/range/access.hpp>
28 #include <range/v3/range/concepts.hpp>
29 #include <range/v3/range/dangling.hpp>
30 #include <range/v3/range/traits.hpp>
31 #include <range/v3/utility/static_const.hpp>
32 
33 #include <range/v3/detail/prologue.hpp>
34 
35 namespace ranges
36 {
37     /// \addtogroup group-algorithms
38     /// @{
39     RANGES_FUNC_BEGIN(unique)
40 
41         /// \brief template function \c unique
42         ///
43         /// range-based version of the \c unique std algorithm
44         ///
45         /// \pre `Rng` is a model of the `forward_range` concept
46         /// \pre `I` is a model of the `forward_iterator` concept
47         /// \pre `S` is a model of the `sentinel_for` concept
48         /// \pre `C` is a model of the `relation` concept
49         ///
50         template(typename I, typename S, typename C = equal_to, typename P = identity)(
51             /// \pre
52             requires sortable<I, C, P> AND sentinel_for<S, I>)
53         I RANGES_FUNC(unique)(I first, S last, C pred = C{}, P proj = P{})
54         {
55             first = adjacent_find(std::move(first), last, std::ref(pred), std::ref(proj));
56 
57             if(first != last)
58             {
59                 for(I i = next(first); ++i != last;)
60                     if(!invoke(pred, invoke(proj, *first), invoke(proj, *i)))
61                         *++first = iter_move(i);
62                 ++first;
63             }
64             return first;
65         }
66 
67         /// \overload
68         template(typename Rng, typename C = equal_to, typename P = identity)(
69             /// \pre
70             requires sortable<iterator_t<Rng>, C, P> AND range<Rng>)
71         borrowed_iterator_t<Rng> //
72         RANGES_FUNC(unique)(Rng && rng, C pred = C{}, P proj = P{}) //
73         {
74             return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
75         }
76 
77     RANGES_FUNC_END(unique)
78 
79     namespace cpp20
80     {
81         using ranges::unique;
82     }
83     /// @}
84 } // namespace ranges
85 
86 #include <range/v3/detail/epilogue.hpp>
87 
88 #endif
89