File: replace_if.hpp

package info (click to toggle)
range-v3 0.12.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,652 kB
  • sloc: cpp: 76,839; xml: 226; sh: 89; python: 34; makefile: 19; perl: 15
file content (157 lines) | stat: -rw-r--r-- 5,440 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/// \file
// Range v3 library
//
//  Copyright Eric Niebler 2013-present
//
//  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)
//
// Project home: https://github.com/ericniebler/range-v3
//

#ifndef RANGES_V3_VIEW_REPLACE_IF_HPP
#define RANGES_V3_VIEW_REPLACE_IF_HPP

#include <type_traits>
#include <utility>

#include <meta/meta.hpp>

#include <concepts/concepts.hpp>

#include <range/v3/range_fwd.hpp>

#include <range/v3/functional/bind_back.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/utility/compressed_pair.hpp>
#include <range/v3/utility/semiregular_box.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/view/all.hpp>
#include <range/v3/view/transform.hpp>
#include <range/v3/view/view.hpp>

#include <range/v3/detail/prologue.hpp>

namespace ranges
{
    /// \cond
    namespace detail
    {
        template<typename Pred, typename Val>
        struct replacer_if_fn : compressed_pair<semiregular_box_t<Pred>, Val>
        {
        private:
            using base_t = compressed_pair<semiregular_box_t<Pred>, Val>;
            using base_t::first;
            using base_t::second;

        public:
            replacer_if_fn() = default;
            constexpr replacer_if_fn(Pred pred, Val new_value)
              : base_t{std::move(pred), std::move(new_value)}
            {}

            template<typename I>
            [[noreturn]] common_type_t<decay_t<unwrap_reference_t<Val const &>>,
                                       iter_value_t<I>> &
            operator()(copy_tag, I const &) const
            {
                RANGES_EXPECT(false);
            }

            template(typename I)(
                requires (!invocable<Pred const &, iter_reference_t<I>>))
            common_reference_t<unwrap_reference_t<Val const &>, iter_reference_t<I>> //
            operator()(I const & i)
            {
                auto && x = *i;
                if(invoke(first(), (decltype(x) &&)x)) //
                    return unwrap_reference(second());
                return (decltype(x) &&)x;
            }
            template(typename I)(
                requires invocable<Pred const &, iter_reference_t<I>>)
            common_reference_t<unwrap_reference_t<Val const &>, iter_reference_t<I>> //
            operator()(I const & i) const
            {
                auto && x = *i;
                if(invoke(first(), (decltype(x) &&)x)) //
                    return unwrap_reference(second());
                return (decltype(x) &&)x;
            }

            template(typename I)(
                requires (!invocable<Pred const &, iter_rvalue_reference_t<I>>))
            common_reference_t<
                unwrap_reference_t<Val const &>, //
                iter_rvalue_reference_t<I>> //
            operator()(move_tag, I const & i)
            {
                auto && x = iter_move(i);
                if(invoke(first(), (decltype(x) &&)x)) //
                    return unwrap_reference(second());
                return (decltype(x) &&)x;
            }
            template(typename I)(
                requires invocable<Pred const &, iter_rvalue_reference_t<I>>)
            common_reference_t< //
                unwrap_reference_t<Val const &>, //
                iter_rvalue_reference_t<I>> //
            operator()(move_tag, I const & i) const
            {
                auto && x = iter_move(i);
                if(invoke(first(), (decltype(x) &&)x)) //
                    return unwrap_reference(second());
                return (decltype(x) &&)x;
            }
        };
    } // namespace detail
    /// \endcond

    /// \addtogroup group-views
    /// @{
    namespace views
    {
        struct replace_if_base_fn
        {
            template(typename Rng, typename Pred, typename Val)(
                requires viewable_range<Rng> AND input_range<Rng> AND
                    indirect_unary_predicate<Pred, iterator_t<Rng>> AND
                    common_with<detail::decay_t<unwrap_reference_t<Val const &>>,
                                range_value_t<Rng>> AND
                    common_reference_with<unwrap_reference_t<Val const &>,
                                          range_reference_t<Rng>> AND
                    common_reference_with<unwrap_reference_t<Val const &>,
                                          range_rvalue_reference_t<Rng>>)
            constexpr replace_if_view<all_t<Rng>, Pred, Val> //
            operator()(Rng && rng, Pred pred, Val new_value) const
            {
                return {all(static_cast<Rng &&>(rng)),
                        {std::move(pred), std::move(new_value)}};
            }
        };

        struct replace_if_fn : replace_if_base_fn
        {
            using replace_if_base_fn::operator();

            template<typename Pred, typename Val>
            constexpr auto operator()(Pred pred, Val new_value) const
            {
                return make_view_closure(bind_back(
                    replace_if_base_fn{}, std::move(pred), std::move(new_value)));
            }
        };

        /// \relates replace_if_fn
        /// \ingroup group-views
        RANGES_INLINE_VARIABLE(replace_if_fn, replace_if)
    } // namespace views
    /// @}
} // namespace ranges

#include <range/v3/detail/epilogue.hpp>

#endif