blob: 01178979017152905474522a08be8adaeb84dfaa [file] [log] [blame]
SiCong Lib63b1192022-01-28 18:24:39 +00001/*
2 * Copyright (c) 2022 Arm Limited.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25#ifndef ARM_COMPUTE_MISC_ITERABLE_H
26#define ARM_COMPUTE_MISC_ITERABLE_H
27namespace arm_compute
28{
29namespace utils
30{
31namespace memory
32{
33namespace
34{
35/** Default polymorphic deep copy function, used by deep_unique_ptr
36 *
37 * @param ptr Potentially polymorphic object to be deep copied
38 * @return template <typename Base, typename Derived>*
39 */
40template <typename Base, typename Derived>
41Base *default_polymorphic_copy(const Base *ptr)
42{
43 static_assert(std::is_base_of<Base, Derived>::value,
44 "Derived is not a specialization of Base");
45 if(ptr == nullptr)
46 {
47 return nullptr;
48 }
49 return new Derived(*static_cast<const Derived *>(ptr));
50}
51} // namespace
52
53/** A deep-copying unique pointer that also supports polymorphic cloning behavior
54 *
55 * @note The == operator compares the dereferenced value instead of the pointer itself.
56 *
57 * @tparam Base Base type
58 */
59template <typename Base>
60class deep_unique_ptr
61{
62public:
63 using CopyFunc = std::function<Base *(const Base *)>;
64
65 deep_unique_ptr(std::nullptr_t val = nullptr) noexcept
66 : _val{ val },
67 _copy{}
68 {
69 }
70 template <typename Derived, typename CopyFuncDerived>
71 deep_unique_ptr(Derived *value, const CopyFuncDerived &copy) noexcept
72 : _val{ value },
73 _copy{ std::move(copy) }
74 {
75 static_assert(std::is_base_of<Base, Derived>::value,
76 "Derived is not a specialization of Base");
77 static_assert(
78 std::is_constructible<CopyFunc, CopyFuncDerived>::value,
79 "CopyFuncDerived is not valid for a copy functor");
80 }
81
82 deep_unique_ptr(const deep_unique_ptr<Base> &ptr)
83 : deep_unique_ptr(ptr.clone())
84 {
85 }
86 deep_unique_ptr &operator=(const deep_unique_ptr<Base> &ptr)
87 {
88 deep_unique_ptr<Base> tmp(ptr);
89 swap(*this, tmp);
90 return *this;
91 }
92
93 deep_unique_ptr(deep_unique_ptr<Base> &&ptr) = default;
94 deep_unique_ptr &operator=(deep_unique_ptr<Base> &&ptr) = default;
95 ~deep_unique_ptr() = default;
96 friend void swap(deep_unique_ptr &ptr0, deep_unique_ptr<Base> &ptr1) noexcept
97 {
98 using std::swap;
99 swap(ptr0._val, ptr1._val);
100 swap(ptr0._copy, ptr1._copy);
101 }
102 Base &operator*() noexcept
103 {
104 return *_val;
105 }
106
107 const Base &operator*() const noexcept
108 {
109 return *_val;
110 }
111
112 Base *operator->() noexcept
113 {
114 return _val.operator->();
115 }
116
117 const Base *operator->() const noexcept
118 {
119 return _val.operator->();
120 }
121
122 Base *get() noexcept
123 {
124 return _val.get();
125 }
126 const Base *get() const noexcept
127 {
128 return _val.get();
129 }
130
131 explicit operator bool() const noexcept
132 {
133 return static_cast<bool>(_val);
134 }
135
136 bool operator==(const deep_unique_ptr<Base> &rhs) const
137 {
138 if(rhs.get() == nullptr && _val == nullptr)
139 {
140 return true;
141 }
142 else if(rhs.get() == nullptr || _val == nullptr)
143 {
144 return false;
145 }
146 else
147 {
148 return (*_val == *rhs);
149 }
150 }
151
152private:
153 deep_unique_ptr clone() const
154 {
155 return { _copy(_val.get()), CopyFunc(_copy) };
156 }
157 std::unique_ptr<Base> _val{ nullptr };
158 CopyFunc _copy{};
159};
160
161/** Utility function to create a polymorphic deep-copying unique pointer
162 *
163 * @tparam Base
164 * @tparam Derived
165 * @tparam CopyFunc
166 * @param temp
167 * @param copy
168 * @return deep_unique_ptr<Base>
169 */
170template <typename Base, typename Derived, typename CopyFunc>
171deep_unique_ptr<Base> make_deep_unique(Derived &&temp, CopyFunc copy)
172{
173 return
174 {
175 new Derived(std::move(temp)),
176 CopyFunc{ std::move(copy) }
177 };
178}
179
180template <typename Base, typename Derived>
181deep_unique_ptr<Base> make_deep_unique(Derived &&temp)
182{
183 static_assert(std::is_base_of<Base, Derived>::value,
184 "Derived is not a specialization of Base");
185
186 return make_deep_unique<Base, Derived>(
187 std::move(temp), default_polymorphic_copy<Base, Derived>);
188}
189
190template <typename Base, typename Derived, typename... Args>
191deep_unique_ptr<Base> make_deep_unique(Args &&... args)
192{
193 static_assert(std::is_constructible<Derived, Args...>::value,
194 "Cannot instantiate Derived from arguments");
195
196 return make_deep_unique<Base, Derived>(
197 std::move(Derived{ std::forward<Args>(args)... }));
198}
199
200} // namespace memory
201} // namespace utils
202} // namespace arm_compute
203#endif // ARM_COMPUTE_MISC_ITERABLE_H