Lagrange
Loading...
Searching...
No Matches
value_ptr.h
1// Source: https://github.com/LoopPerfect/valuable
2// SPDX-License-Identifier: MIT
3//
4// This file has been modified by Adobe.
5//
6// All modifications are Copyright 2022 Adobe.
7//
8// MIT License
9//
10// Copyright (c) 2017 LoopPerfect
11//
12// Permission is hereby granted, free of charge, to any person obtaining a copy
13// of this software and associated documentation files (the "Software"), to deal
14// in the Software without restriction, including without limitation the rights
15// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16// copies of the Software, and to permit persons to whom the Software is
17// furnished to do so, subject to the following conditions:
18//
19// The above copyright notice and this permission notice shall be included in all
20// copies or substantial portions of the Software.
22// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28// SOFTWARE.
29
30#pragma once
31
32#include <memory>
33
34#ifndef LA_DECLSPEC_EMPTY_BASES
35 #ifdef _MSC_VER
36 #define LA_DECLSPEC_EMPTY_BASES __declspec(empty_bases)
37 #else
38 #define LA_DECLSPEC_EMPTY_BASES
39 #endif
40#endif
41
42namespace lagrange {
43
45
46namespace detail {
47
48struct spacer
49{
50};
51
52// For details of class_tag use here, see
53// https://mortoray.com/2013/06/03/overriding-the-broken-universal-reference-t/
54template <typename T>
55struct class_tag
56{
57};
58
59template <class T, class Deleter, class T2>
60struct LA_DECLSPEC_EMPTY_BASES compressed_ptr : std::unique_ptr<T, Deleter>, T2
61{
62 using T1 = std::unique_ptr<T, Deleter>;
63 compressed_ptr() = default;
64 compressed_ptr(compressed_ptr&&) = default;
65 compressed_ptr(const compressed_ptr&) = default;
66 compressed_ptr(T2&& a2)
67 : T2(std::move(a2))
68 {}
69 compressed_ptr(const T2& a2)
70 : T2(a2)
71 {}
72 template <typename A1>
73 compressed_ptr(A1&& a1)
74 : compressed_ptr(
75 std::forward<A1>(a1),
76 class_tag<typename std::decay<A1>::type>(),
77 spacer(),
78 spacer())
79 {}
80 template <typename A1, typename A2>
81 compressed_ptr(A1&& a1, A2&& a2)
82 : compressed_ptr(
83 std::forward<A1>(a1),
84 std::forward<A2>(a2),
85 class_tag<typename std::decay<A2>::type>(),
86 spacer())
87 {}
88 template <typename A1, typename A2, typename A3>
89 compressed_ptr(A1&& a1, A2&& a2, A3&& a3)
90 : T1(std::forward<A1>(a1), std::forward<A2>(a2))
91 , T2(std::forward<A3>(a3))
92 {}
93
94 template <typename A1>
95 compressed_ptr(A1&& a1, class_tag<typename std::decay<A1>::type>, spacer, spacer)
96 : T1(std::forward<A1>(a1))
97 {}
98 template <typename A1, typename A2>
99 compressed_ptr(A1&& a1, A2&& a2, class_tag<Deleter>, spacer)
100 : T1(std::forward<A1>(a1), std::forward<A2>(a2))
101 {}
102 template <typename A1, typename A2>
103 compressed_ptr(A1&& a1, A2&& a2, class_tag<T2>, spacer)
104 : T1(std::forward<A1>(a1))
105 , T2(std::forward<A2>(a2))
106 {}
107};
108
109} // namespace detail
110
111template <typename T>
112struct default_clone
113{
114 default_clone() = default;
115 T* operator()(T const& x) const { return new T(x); }
116 T* operator()(T&& x) const { return new T(std::move(x)); }
117};
118
120
131template <class T, class Cloner = default_clone<T>, class Deleter = std::default_delete<T>>
132class value_ptr
133{
134 ::lagrange::detail::compressed_ptr<T, Deleter, Cloner> ptr_;
135
136 std::unique_ptr<T, Deleter>& ptr() { return ptr_; }
137 std::unique_ptr<T, Deleter> const& ptr() const { return ptr_; }
138
139 T* clone(T const& x) const { return get_cloner()(x); }
140
141public:
142 using pointer = T*;
143 using element_type = T;
144 using cloner_type = Cloner;
145 using deleter_type = Deleter;
146
147 value_ptr() = default;
148
149 value_ptr(const T& value)
150 : ptr_(cloner_type()(value))
151 {}
152 value_ptr(T&& value)
153 : ptr_(cloner_type()(std::move(value)))
154 {}
155
156 value_ptr(const Cloner& value)
157 : ptr_(value)
158 {}
159 value_ptr(Cloner&& value)
160 : ptr_(value)
161 {}
162
163 template <typename V, typename ClonerOrDeleter>
164 value_ptr(V&& value, ClonerOrDeleter&& a2)
165 : ptr_(std::forward<V>(value), std::forward<ClonerOrDeleter>(a2))
166 {}
167
168 template <typename V, typename C, typename D>
169 value_ptr(V&& value, C&& cloner, D&& deleter)
170 : ptr_(std::forward<V>(value), std::forward<D>(deleter), std::forward<C>(cloner))
171 {}
172
173 value_ptr(value_ptr const& v)
174 : ptr_{nullptr, v.get_cloner()}
175 {
176 if (v) {
177 ptr().reset(clone(*v));
178 }
179 }
180 value_ptr(value_ptr&& v) = default;
181
182 explicit value_ptr(pointer value)
183 : ptr_(value)
184 {}
185 pointer release() { return ptr().release(); }
186
187 T* get() noexcept { return ptr().get(); }
188 T const* get() const noexcept { return ptr().get(); }
189
190 Cloner& get_cloner() noexcept { return ptr_; }
191 Cloner const& get_cloner() const noexcept { return ptr_; }
192
193 Deleter& get_deleter() noexcept { return ptr_; }
194 Deleter const& get_deleter() const noexcept { return ptr_; }
195
196 T& operator*() { return *get(); }
197 T const& operator*() const { return *get(); }
198
199 T const* operator->() const noexcept { return get(); }
200 T* operator->() noexcept { return get(); }
201
202 value_ptr<T>& operator=(value_ptr&& v) noexcept
203 {
204 ptr() = std::move(v.ptr());
205 get_cloner() = std::move(v.get_cloner());
206 return *this;
207 }
208
209 value_ptr<T>& operator=(value_ptr const& v)
210 {
211 ptr().reset(v.get_cloner()(*v));
212 get_cloner() = v.get_cloner();
213 return *this;
214 }
215
216 operator bool() const noexcept { return !!ptr(); }
217 ~value_ptr() = default;
218};
219
232template <class T, class... Args>
234{
235 return value_ptr<T>(new T(std::forward<Args>(args)...));
236}
237
238} // namespace lagrange
Smart pointer with value semantics.
Definition value_ptr.h:133
value_ptr< T > make_value_ptr(Args &&... args)
Helper function to create a value_ptr for a given type.
Definition value_ptr.h:233
Main namespace for Lagrange.
Definition project.cpp:27