##// END OF EJS Templates
add spimpl formatting (from windows)
perrinel -
r61:396fde467fc9
parent child
Show More
@@ -1,458 +1,462
1 /*
1 /*
2 ====================================================================
2 ====================================================================
3 A Smart Pointer to IMPLementation (i.e. Smart PIMPL or just SPIMPL).
3 A Smart Pointer to IMPLementation (i.e. Smart PIMPL or just SPIMPL).
4 ====================================================================
4 ====================================================================
5
5
6 Version: 1.1
6 Version: 1.1
7
7
8 Latest version:
8 Latest version:
9 https://github.com/oliora/samples/blob/master/spimpl.h
9 https://github.com/oliora/samples/blob/master/spimpl.h
10 Rationale and description:
10 Rationale and description:
11 http://oliora.github.io/2015/12/29/pimpl-and-rule-of-zero.html
11 http://oliora.github.io/2015/12/29/pimpl-and-rule-of-zero.html
12
12
13 Copyright (c) 2015 Andrey Upadyshev (oliora@gmail.com)
13 Copyright (c) 2015 Andrey Upadyshev (oliora@gmail.com)
14
14
15 Distributed under the Boost Software License, Version 1.0.
15 Distributed under the Boost Software License, Version 1.0.
16 See http://www.boost.org/LICENSE_1_0.txt
16 See http://www.boost.org/LICENSE_1_0.txt
17
17
18 Changes history
18 Changes history
19 ---------------
19 ---------------
20 v1.1:
20 v1.1:
21 - auto_ptr support is disabled by default for C++17 compatibility
21 - auto_ptr support is disabled by default for C++17 compatibility
22 v1.0:
22 v1.0:
23 - Released
23 - Released
24 */
24 */
25
25
26 #ifndef SPIMPL_H_
26 #ifndef SPIMPL_H_
27 #define SPIMPL_H_
27 #define SPIMPL_H_
28
28
29 #include <cassert>
29 #include <cassert>
30 #include <memory>
30 #include <memory>
31 #include <type_traits>
31 #include <type_traits>
32
32
33 #if defined _MSC_VER && _MSC_VER < 1900 // MS Visual Studio before VS2015
33 #if defined _MSC_VER && _MSC_VER < 1900 // MS Visual Studio before VS2015
34 #define SPIMPL_NO_CPP11_NOEXCEPT
34 #define SPIMPL_NO_CPP11_NOEXCEPT
35 #define SPIMPL_NO_CPP11_CONSTEXPR
35 #define SPIMPL_NO_CPP11_CONSTEXPR
36 #define SPIMPL_NO_CPP11_DEFAULT_MOVE_SPEC_FUNC
36 #define SPIMPL_NO_CPP11_DEFAULT_MOVE_SPEC_FUNC
37 #endif
37 #endif
38
38
39 #if !defined SPIMPL_NO_CPP11_NOEXCEPT
39 #if !defined SPIMPL_NO_CPP11_NOEXCEPT
40 #define SPIMPL_NOEXCEPT noexcept
40 #define SPIMPL_NOEXCEPT noexcept
41 #else
41 #else
42 #define SPIMPL_NOEXCEPT
42 #define SPIMPL_NOEXCEPT
43 #endif
43 #endif
44
44
45 #if !defined SPIMPL_NO_CPP11_CONSTEXPR
45 #if !defined SPIMPL_NO_CPP11_CONSTEXPR
46 #define SPIMPL_CONSTEXPR constexpr
46 #define SPIMPL_CONSTEXPR constexpr
47 #else
47 #else
48 #define SPIMPL_CONSTEXPR
48 #define SPIMPL_CONSTEXPR
49 #endif
49 #endif
50
50
51 // define SPIMPL_HAS_AUTO_PTR to enable constructor and assignment operator that accept
51 // define SPIMPL_HAS_AUTO_PTR to enable constructor and assignment operator that accept
52 // std::auto_ptr
52 // std::auto_ptr
53 // TODO: auto detect std::auto_ptr support
53 // TODO: auto detect std::auto_ptr support
54
54
55
55
56 namespace spimpl {
56 namespace spimpl {
57 namespace details {
57 namespace details {
58 template <class T>
58 template <class T>
59 T *default_copy(T *src)
59 T *default_copy(T *src)
60 {
60 {
61 static_assert(sizeof(T) > 0, "default_copy cannot copy incomplete type");
61 static_assert(sizeof(T) > 0, "default_copy cannot copy incomplete type");
62 static_assert(!std::is_void<T>::value, "default_copy cannot copy incomplete type");
62 static_assert(!std::is_void<T>::value, "default_copy cannot copy incomplete type");
63 return new T(*src);
63 return new T(*src);
64 }
64 }
65
65
66 template <class T>
66 template <class T>
67 void default_delete(T *p) SPIMPL_NOEXCEPT
67 void default_delete(T *p) SPIMPL_NOEXCEPT
68 {
68 {
69 static_assert(sizeof(T) > 0, "default_delete cannot delete incomplete type");
69 static_assert(sizeof(T) > 0, "default_delete cannot delete incomplete type");
70 static_assert(!std::is_void<T>::value, "default_delete cannot delete incomplete type");
70 static_assert(!std::is_void<T>::value, "default_delete cannot delete incomplete type");
71 delete p;
71 delete p;
72 }
72 }
73
73
74 template <class T>
74 template <class T>
75 struct default_deleter {
75 struct default_deleter {
76 using type = void (*)(T *);
76 using type = void (*)(T *);
77 };
77 };
78
78
79 template <class T>
79 template <class T>
80 using default_deleter_t = typename default_deleter<T>::type;
80 using default_deleter_t = typename default_deleter<T>::type;
81
81
82 template <class T>
82 template <class T>
83 struct default_copier {
83 struct default_copier {
84 using type = T *(*)(T *);
84 using type = T *(*)(T *);
85 };
85 };
86
86
87 template <class T>
87 template <class T>
88 using default_copier_t = typename default_copier<T>::type;
88 using default_copier_t = typename default_copier<T>::type;
89
89
90 template <class T, class D, class C>
90 template <class T, class D, class C>
91 struct is_default_manageable
91 struct is_default_manageable
92 : public std::integral_constant<bool, std::is_same<D, default_deleter_t<T> >::value
92 : public std::integral_constant<bool,
93 std::is_same<D, default_deleter_t<T> >::value
93 && std::is_same<C, default_copier_t<T> >::value> {
94 && std::is_same<C, default_copier_t<T> >::value> {
94 };
95 };
95 }
96 }
96
97
97
98
98 template <class T, class Deleter = details::default_deleter_t<T>,
99 template <class T, class Deleter = details::default_deleter_t<T>,
99 class Copier = details::default_copier_t<T> >
100 class Copier = details::default_copier_t<T> >
100 class impl_ptr {
101 class impl_ptr {
101 private:
102 private:
102 static_assert(!std::is_array<T>::value,
103 static_assert(!std::is_array<T>::value,
103 "impl_ptr specialization for arrays is not implemented");
104 "impl_ptr specialization for arrays is not implemented");
104 struct dummy_t_ {
105 struct dummy_t_ {
105 int dummy__;
106 int dummy__;
106 };
107 };
107
108
108 public:
109 public:
109 using pointer = T *;
110 using pointer = T *;
110 using element_type = T;
111 using element_type = T;
111 using copier_type = typename std::decay<Copier>::type;
112 using copier_type = typename std::decay<Copier>::type;
112 using deleter_type = typename std::decay<Deleter>::type;
113 using deleter_type = typename std::decay<Deleter>::type;
113 using unique_ptr_type = std::unique_ptr<T, deleter_type>;
114 using unique_ptr_type = std::unique_ptr<T, deleter_type>;
114 using is_default_manageable = details::is_default_manageable<T, deleter_type, copier_type>;
115 using is_default_manageable = details::is_default_manageable<T, deleter_type, copier_type>;
115
116
116 SPIMPL_CONSTEXPR impl_ptr() SPIMPL_NOEXCEPT : ptr_(nullptr, deleter_type{}),
117 SPIMPL_CONSTEXPR impl_ptr() SPIMPL_NOEXCEPT : ptr_(nullptr, deleter_type{}),
117 copier_(copier_type{})
118 copier_(copier_type{})
118 {
119 {
119 }
120 }
120
121
121 SPIMPL_CONSTEXPR impl_ptr(std::nullptr_t) SPIMPL_NOEXCEPT : impl_ptr() {}
122 SPIMPL_CONSTEXPR impl_ptr(std::nullptr_t) SPIMPL_NOEXCEPT : impl_ptr() {}
122
123
123 template <class D, class C>
124 template <class D, class C>
124 impl_ptr(pointer p, D &&d, C &&c,
125 impl_ptr(pointer p, D &&d, C &&c,
125 typename std::enable_if<std::is_convertible<D, deleter_type>::value
126 typename std::enable_if<std::is_convertible<D, deleter_type>::value
126 && std::is_convertible<C, copier_type>::value,
127 && std::is_convertible<C, copier_type>::value,
127 dummy_t_>::type
128 dummy_t_>::type
128 = dummy_t_()) SPIMPL_NOEXCEPT : ptr_(std::move(p), std::forward<D>(d)),
129 = dummy_t_()) SPIMPL_NOEXCEPT : ptr_(std::move(p), std::forward<D>(d)),
129 copier_(std::forward<C>(c))
130 copier_(std::forward<C>(c))
130 {
131 {
131 }
132 }
132
133
133 template <class U>
134 template <class U>
134 impl_ptr(U *u, typename std::enable_if<std::is_convertible<U *, pointer>::value
135 impl_ptr(U *u,
136 typename std::enable_if<std::is_convertible<U *, pointer>::value
135 && is_default_manageable::value,
137 && is_default_manageable::value,
136 dummy_t_>::type
138 dummy_t_>::type
137 = dummy_t_()) SPIMPL_NOEXCEPT
139 = dummy_t_()) SPIMPL_NOEXCEPT
138 : impl_ptr(u, &details::default_delete<T>, &details::default_copy<T>)
140 : impl_ptr(u, &details::default_delete<T>, &details::default_copy<T>)
139 {
141 {
140 }
142 }
141
143
142 impl_ptr(const impl_ptr &r) : impl_ptr(r.clone()) {}
144 impl_ptr(const impl_ptr &r) : impl_ptr(r.clone()) {}
143
145
144 #ifndef SPIMPL_NO_CPP11_DEFAULT_MOVE_SPEC_FUNC
146 #ifndef SPIMPL_NO_CPP11_DEFAULT_MOVE_SPEC_FUNC
145 impl_ptr(impl_ptr &&r) SPIMPL_NOEXCEPT = default;
147 impl_ptr(impl_ptr &&r) SPIMPL_NOEXCEPT = default;
146 #else
148 #else
147 impl_ptr(impl_ptr &&r) SPIMPL_NOEXCEPT : ptr_(std::move(r.ptr_)), copier_(std::move(r.copier_))
149 impl_ptr(impl_ptr &&r) SPIMPL_NOEXCEPT : ptr_(std::move(r.ptr_)), copier_(std::move(r.copier_))
148 {
150 {
149 }
151 }
150 #endif
152 #endif
151
153
152 #ifdef SPIMPL_HAS_AUTO_PTR
154 #ifdef SPIMPL_HAS_AUTO_PTR
153 template <class U>
155 template <class U>
154 impl_ptr(std::auto_ptr<U> &&u, typename std::enable_if<std::is_convertible<U *, pointer>::value
156 impl_ptr(std::auto_ptr<U> &&u,
157 typename std::enable_if<std::is_convertible<U *, pointer>::value
155 && is_default_manageable::value,
158 && is_default_manageable::value,
156 dummy_t_>::type
159 dummy_t_>::type
157 = dummy_t_()) SPIMPL_NOEXCEPT
160 = dummy_t_()) SPIMPL_NOEXCEPT : ptr_(u.release(), &details::default_delete<T>),
158 : ptr_(u.release(), &details::default_delete<T>),
159 copier_(&details::default_copy<T>)
161 copier_(&details::default_copy<T>)
160 {
162 {
161 }
163 }
162 #endif
164 #endif
163
165
164 template <class U>
166 template <class U>
165 impl_ptr(std::unique_ptr<U> &&u,
167 impl_ptr(std::unique_ptr<U> &&u,
166 typename std::enable_if<std::is_convertible<U *, pointer>::value
168 typename std::enable_if<std::is_convertible<U *, pointer>::value
167 && is_default_manageable::value,
169 && is_default_manageable::value,
168 dummy_t_>::type
170 dummy_t_>::type
169 = dummy_t_()) SPIMPL_NOEXCEPT : ptr_(u.release(), &details::default_delete<T>),
171 = dummy_t_()) SPIMPL_NOEXCEPT : ptr_(u.release(), &details::default_delete<T>),
170 copier_(&details::default_copy<T>)
172 copier_(&details::default_copy<T>)
171 {
173 {
172 }
174 }
173
175
174 template <class U, class D, class C>
176 template <class U, class D, class C>
175 impl_ptr(std::unique_ptr<U, D> &&u, C &&c,
177 impl_ptr(std::unique_ptr<U, D> &&u, C &&c,
176 typename std::enable_if<std::is_convertible<U *, pointer>::value
178 typename std::enable_if<std::is_convertible<U *, pointer>::value
177 && std::is_convertible<D, deleter_type>::value
179 && std::is_convertible<D, deleter_type>::value
178 && std::is_convertible<C, copier_type>::value,
180 && std::is_convertible<C, copier_type>::value,
179 dummy_t_>::type
181 dummy_t_>::type
180 = dummy_t_()) SPIMPL_NOEXCEPT : ptr_(std::move(u)),
182 = dummy_t_()) SPIMPL_NOEXCEPT : ptr_(std::move(u)),
181 copier_(std::forward<C>(c))
183 copier_(std::forward<C>(c))
182 {
184 {
183 }
185 }
184
186
185 template <class U, class D, class C>
187 template <class U, class D, class C>
186 impl_ptr(impl_ptr<U, D, C> &&u,
188 impl_ptr(impl_ptr<U, D, C> &&u,
187 typename std::enable_if<std::is_convertible<U *, pointer>::value
189 typename std::enable_if<std::is_convertible<U *, pointer>::value
188 && std::is_convertible<D, deleter_type>::value
190 && std::is_convertible<D, deleter_type>::value
189 && std::is_convertible<C, copier_type>::value,
191 && std::is_convertible<C, copier_type>::value,
190 dummy_t_>::type
192 dummy_t_>::type
191 = dummy_t_()) SPIMPL_NOEXCEPT : ptr_(std::move(u.ptr_)),
193 = dummy_t_()) SPIMPL_NOEXCEPT : ptr_(std::move(u.ptr_)),
192 copier_(std::move(u.copier_))
194 copier_(std::move(u.copier_))
193 {
195 {
194 }
196 }
195
197
196 impl_ptr &operator=(const impl_ptr &r)
198 impl_ptr &operator=(const impl_ptr &r)
197 {
199 {
198 if (this == &r)
200 if (this == &r)
199 return *this;
201 return *this;
200
202
201 return operator=(r.clone());
203 return operator=(r.clone());
202 }
204 }
203
205
204 #ifndef SPIMPL_NO_CPP11_DEFAULT_MOVE_SPEC_FUNC
206 #ifndef SPIMPL_NO_CPP11_DEFAULT_MOVE_SPEC_FUNC
205 impl_ptr &operator=(impl_ptr &&r) SPIMPL_NOEXCEPT = default;
207 impl_ptr &operator=(impl_ptr &&r) SPIMPL_NOEXCEPT = default;
206 #else
208 #else
207 impl_ptr &operator=(impl_ptr &&r) SPIMPL_NOEXCEPT
209 impl_ptr &operator=(impl_ptr &&r) SPIMPL_NOEXCEPT
208 {
210 {
209 ptr_ = std::move(r.ptr_);
211 ptr_ = std::move(r.ptr_);
210 copier_ = std::move(r.copier_);
212 copier_ = std::move(r.copier_);
211 return *this;
213 return *this;
212 }
214 }
213 #endif
215 #endif
214
216
215 template <class U, class D, class C>
217 template <class U, class D, class C>
216 typename std::enable_if<std::is_convertible<U *, pointer>::value
218 typename std::enable_if<std::is_convertible<U *, pointer>::value
217 && std::is_convertible<D, deleter_type>::value
219 && std::is_convertible<D, deleter_type>::value
218 && std::is_convertible<C, copier_type>::value,
220 && std::is_convertible<C, copier_type>::value,
219 impl_ptr &>::type
221 impl_ptr &>::type
220 operator=(impl_ptr<U, D, C> &&u) SPIMPL_NOEXCEPT
222 operator=(impl_ptr<U, D, C> &&u) SPIMPL_NOEXCEPT
221 {
223 {
222 ptr_ = std::move(u.ptr_);
224 ptr_ = std::move(u.ptr_);
223 copier_ = std::move(u.copier_);
225 copier_ = std::move(u.copier_);
224 return *this;
226 return *this;
225 }
227 }
226
228
227 template <class U, class D, class C>
229 template <class U, class D, class C>
228 typename std::enable_if<std::is_convertible<U *, pointer>::value
230 typename std::enable_if<std::is_convertible<U *, pointer>::value
229 && std::is_convertible<D, deleter_type>::value
231 && std::is_convertible<D, deleter_type>::value
230 && std::is_convertible<C, copier_type>::value,
232 && std::is_convertible<C, copier_type>::value,
231 impl_ptr &>::type
233 impl_ptr &>::type
232 operator=(const impl_ptr<U, D, C> &u)
234 operator=(const impl_ptr<U, D, C> &u)
233 {
235 {
234 return operator=(u.clone());
236 return operator=(u.clone());
235 }
237 }
236
238
237 //
239 //
238
240
239 #ifdef SPIMPL_HAS_AUTO_PTR
241 #ifdef SPIMPL_HAS_AUTO_PTR
240 template <class U>
242 template <class U>
241 typename std::enable_if<
243 typename std::enable_if<std::is_convertible<U *, pointer>::value
242 std::is_convertible<U *, pointer>::value && is_default_manageable::value, impl_ptr &>::type
244 && is_default_manageable::value,
245 impl_ptr &>::type
243 operator=(std::auto_ptr<U> &&u) SPIMPL_NOEXCEPT
246 operator=(std::auto_ptr<U> &&u) SPIMPL_NOEXCEPT
244 {
247 {
245 return operator=(impl_ptr(std::move(u)));
248 return operator=(impl_ptr(std::move(u)));
246 }
249 }
247 #endif
250 #endif
248
251
249 template <class U>
252 template <class U>
250 typename std::enable_if<
253 typename std::enable_if<std::is_convertible<U *, pointer>::value
251 std::is_convertible<U *, pointer>::value && is_default_manageable::value, impl_ptr &>::type
254 && is_default_manageable::value,
255 impl_ptr &>::type
252 operator=(std::unique_ptr<U> &&u) SPIMPL_NOEXCEPT
256 operator=(std::unique_ptr<U> &&u) SPIMPL_NOEXCEPT
253 {
257 {
254 return operator=(impl_ptr(std::move(u)));
258 return operator=(impl_ptr(std::move(u)));
255 }
259 }
256
260
257 impl_ptr clone() const
261 impl_ptr clone() const
258 {
262 {
259 return impl_ptr(ptr_ ? copier_(ptr_.get()) : nullptr, ptr_.get_deleter(), copier_);
263 return impl_ptr(ptr_ ? copier_(ptr_.get()) : nullptr, ptr_.get_deleter(), copier_);
260 }
264 }
261
265
262 typename std::remove_reference<T>::type &operator*() const { return *ptr_; }
266 typename std::remove_reference<T>::type &operator*() const { return *ptr_; }
263 pointer operator->() const SPIMPL_NOEXCEPT { return get(); }
267 pointer operator->() const SPIMPL_NOEXCEPT { return get(); }
264 pointer get() const SPIMPL_NOEXCEPT { return ptr_.get(); }
268 pointer get() const SPIMPL_NOEXCEPT { return ptr_.get(); }
265
269
266 void swap(impl_ptr &u) SPIMPL_NOEXCEPT
270 void swap(impl_ptr &u) SPIMPL_NOEXCEPT
267 {
271 {
268 using std::swap;
272 using std::swap;
269 ptr_.swap(u.ptr_);
273 ptr_.swap(u.ptr_);
270 swap(copier_, u.copier_);
274 swap(copier_, u.copier_);
271 }
275 }
272
276
273 pointer release() SPIMPL_NOEXCEPT { return ptr_.release(); }
277 pointer release() SPIMPL_NOEXCEPT { return ptr_.release(); }
274
278
275 unique_ptr_type release_unique() SPIMPL_NOEXCEPT { return std::move(ptr_); }
279 unique_ptr_type release_unique() SPIMPL_NOEXCEPT { return std::move(ptr_); }
276
280
277 explicit operator bool() const SPIMPL_NOEXCEPT { return static_cast<bool>(ptr_); }
281 explicit operator bool() const SPIMPL_NOEXCEPT { return static_cast<bool>(ptr_); }
278
282
279 typename std::remove_reference<deleter_type>::type &get_deleter() SPIMPL_NOEXCEPT
283 typename std::remove_reference<deleter_type>::type &get_deleter() SPIMPL_NOEXCEPT
280 {
284 {
281 return ptr_.get_deleter();
285 return ptr_.get_deleter();
282 }
286 }
283 const typename std::remove_reference<deleter_type>::type &get_deleter() const SPIMPL_NOEXCEPT
287 const typename std::remove_reference<deleter_type>::type &get_deleter() const SPIMPL_NOEXCEPT
284 {
288 {
285 return ptr_.get_deleter();
289 return ptr_.get_deleter();
286 }
290 }
287
291
288 typename std::remove_reference<copier_type>::type &get_copier() SPIMPL_NOEXCEPT
292 typename std::remove_reference<copier_type>::type &get_copier() SPIMPL_NOEXCEPT
289 {
293 {
290 return copier_;
294 return copier_;
291 }
295 }
292 const typename std::remove_reference<copier_type>::type &get_copier() const SPIMPL_NOEXCEPT
296 const typename std::remove_reference<copier_type>::type &get_copier() const SPIMPL_NOEXCEPT
293 {
297 {
294 return copier_;
298 return copier_;
295 }
299 }
296
300
297 private:
301 private:
298 unique_ptr_type ptr_;
302 unique_ptr_type ptr_;
299 copier_type copier_;
303 copier_type copier_;
300 };
304 };
301
305
302
306
303 template <class T, class D, class C>
307 template <class T, class D, class C>
304 inline void swap(impl_ptr<T, D, C> &l, impl_ptr<T, D, C> &r) SPIMPL_NOEXCEPT
308 inline void swap(impl_ptr<T, D, C> &l, impl_ptr<T, D, C> &r) SPIMPL_NOEXCEPT
305 {
309 {
306 l.swap(r);
310 l.swap(r);
307 }
311 }
308
312
309
313
310 template <class T1, class D1, class C1, class T2, class D2, class C2>
314 template <class T1, class D1, class C1, class T2, class D2, class C2>
311 inline bool operator==(const impl_ptr<T1, D1, C1> &l, const impl_ptr<T2, D2, C2> &r)
315 inline bool operator==(const impl_ptr<T1, D1, C1> &l, const impl_ptr<T2, D2, C2> &r)
312 {
316 {
313 return l.get() == r.get();
317 return l.get() == r.get();
314 }
318 }
315
319
316 template <class T1, class D1, class C1, class T2, class D2, class C2>
320 template <class T1, class D1, class C1, class T2, class D2, class C2>
317 inline bool operator!=(const impl_ptr<T1, D1, C1> &l, const impl_ptr<T2, D2, C2> &r)
321 inline bool operator!=(const impl_ptr<T1, D1, C1> &l, const impl_ptr<T2, D2, C2> &r)
318 {
322 {
319 return !(l == r);
323 return !(l == r);
320 }
324 }
321
325
322 template <class T1, class D1, class C1, class T2, class D2, class C2>
326 template <class T1, class D1, class C1, class T2, class D2, class C2>
323 inline bool operator<(const impl_ptr<T1, D1, C1> &l, const impl_ptr<T2, D2, C2> &r)
327 inline bool operator<(const impl_ptr<T1, D1, C1> &l, const impl_ptr<T2, D2, C2> &r)
324 {
328 {
325 using P1 = typename impl_ptr<T1, D1, C1>::pointer;
329 using P1 = typename impl_ptr<T1, D1, C1>::pointer;
326 using P2 = typename impl_ptr<T2, D2, C2>::pointer;
330 using P2 = typename impl_ptr<T2, D2, C2>::pointer;
327 using CT = typename std::common_type<P1, P2>::type;
331 using CT = typename std::common_type<P1, P2>::type;
328 return std::less<CT>()(l.get(), r.get());
332 return std::less<CT>()(l.get(), r.get());
329 }
333 }
330
334
331 template <class T1, class D1, class C1, class T2, class D2, class C2>
335 template <class T1, class D1, class C1, class T2, class D2, class C2>
332 inline bool operator>(const impl_ptr<T1, D1, C1> &l, const impl_ptr<T2, D2, C2> &r)
336 inline bool operator>(const impl_ptr<T1, D1, C1> &l, const impl_ptr<T2, D2, C2> &r)
333 {
337 {
334 return r < l;
338 return r < l;
335 }
339 }
336
340
337 template <class T1, class D1, class C1, class T2, class D2, class C2>
341 template <class T1, class D1, class C1, class T2, class D2, class C2>
338 inline bool operator<=(const impl_ptr<T1, D1, C1> &l, const impl_ptr<T2, D2, C2> &r)
342 inline bool operator<=(const impl_ptr<T1, D1, C1> &l, const impl_ptr<T2, D2, C2> &r)
339 {
343 {
340 return !(r < l);
344 return !(r < l);
341 }
345 }
342
346
343 template <class T1, class D1, class C1, class T2, class D2, class C2>
347 template <class T1, class D1, class C1, class T2, class D2, class C2>
344 inline bool operator>=(const impl_ptr<T1, D1, C1> &l, const impl_ptr<T2, D2, C2> &r)
348 inline bool operator>=(const impl_ptr<T1, D1, C1> &l, const impl_ptr<T2, D2, C2> &r)
345 {
349 {
346 return !(l < r);
350 return !(l < r);
347 }
351 }
348
352
349 template <class T, class D, class C>
353 template <class T, class D, class C>
350 inline bool operator==(const impl_ptr<T, D, C> &p, std::nullptr_t) SPIMPL_NOEXCEPT
354 inline bool operator==(const impl_ptr<T, D, C> &p, std::nullptr_t) SPIMPL_NOEXCEPT
351 {
355 {
352 return !p;
356 return !p;
353 }
357 }
354
358
355 template <class T, class D, class C>
359 template <class T, class D, class C>
356 inline bool operator==(std::nullptr_t, const impl_ptr<T, D, C> &p) SPIMPL_NOEXCEPT
360 inline bool operator==(std::nullptr_t, const impl_ptr<T, D, C> &p) SPIMPL_NOEXCEPT
357 {
361 {
358 return !p;
362 return !p;
359 }
363 }
360
364
361 template <class T, class D, class C>
365 template <class T, class D, class C>
362 inline bool operator!=(const impl_ptr<T, D, C> &p, std::nullptr_t) SPIMPL_NOEXCEPT
366 inline bool operator!=(const impl_ptr<T, D, C> &p, std::nullptr_t) SPIMPL_NOEXCEPT
363 {
367 {
364 return static_cast<bool>(p);
368 return static_cast<bool>(p);
365 }
369 }
366
370
367 template <class T, class D, class C>
371 template <class T, class D, class C>
368 inline bool operator!=(std::nullptr_t, const impl_ptr<T, D, C> &p) SPIMPL_NOEXCEPT
372 inline bool operator!=(std::nullptr_t, const impl_ptr<T, D, C> &p) SPIMPL_NOEXCEPT
369 {
373 {
370 return static_cast<bool>(p);
374 return static_cast<bool>(p);
371 }
375 }
372
376
373 template <class T, class D, class C>
377 template <class T, class D, class C>
374 inline bool operator<(const impl_ptr<T, D, C> &l, std::nullptr_t)
378 inline bool operator<(const impl_ptr<T, D, C> &l, std::nullptr_t)
375 {
379 {
376 using P = typename impl_ptr<T, D, C>::pointer;
380 using P = typename impl_ptr<T, D, C>::pointer;
377 return std::less<P>()(l.get(), nullptr);
381 return std::less<P>()(l.get(), nullptr);
378 }
382 }
379
383
380 template <class T, class D, class C>
384 template <class T, class D, class C>
381 inline bool operator<(std::nullptr_t, const impl_ptr<T, D, C> &p)
385 inline bool operator<(std::nullptr_t, const impl_ptr<T, D, C> &p)
382 {
386 {
383 using P = typename impl_ptr<T, D, C>::pointer;
387 using P = typename impl_ptr<T, D, C>::pointer;
384 return std::less<P>()(nullptr, p.get());
388 return std::less<P>()(nullptr, p.get());
385 }
389 }
386
390
387 template <class T, class D, class C>
391 template <class T, class D, class C>
388 inline bool operator>(const impl_ptr<T, D, C> &p, std::nullptr_t)
392 inline bool operator>(const impl_ptr<T, D, C> &p, std::nullptr_t)
389 {
393 {
390 return nullptr < p;
394 return nullptr < p;
391 }
395 }
392
396
393 template <class T, class D, class C>
397 template <class T, class D, class C>
394 inline bool operator>(std::nullptr_t, const impl_ptr<T, D, C> &p)
398 inline bool operator>(std::nullptr_t, const impl_ptr<T, D, C> &p)
395 {
399 {
396 return p < nullptr;
400 return p < nullptr;
397 }
401 }
398
402
399 template <class T, class D, class C>
403 template <class T, class D, class C>
400 inline bool operator<=(const impl_ptr<T, D, C> &p, std::nullptr_t)
404 inline bool operator<=(const impl_ptr<T, D, C> &p, std::nullptr_t)
401 {
405 {
402 return !(nullptr < p);
406 return !(nullptr < p);
403 }
407 }
404
408
405 template <class T, class D, class C>
409 template <class T, class D, class C>
406 inline bool operator<=(std::nullptr_t, const impl_ptr<T, D, C> &p)
410 inline bool operator<=(std::nullptr_t, const impl_ptr<T, D, C> &p)
407 {
411 {
408 return !(p < nullptr);
412 return !(p < nullptr);
409 }
413 }
410
414
411 template <class T, class D, class C>
415 template <class T, class D, class C>
412 inline bool operator>=(const impl_ptr<T, D, C> &p, std::nullptr_t)
416 inline bool operator>=(const impl_ptr<T, D, C> &p, std::nullptr_t)
413 {
417 {
414 return !(p < nullptr);
418 return !(p < nullptr);
415 }
419 }
416
420
417 template <class T, class D, class C>
421 template <class T, class D, class C>
418 inline bool operator>=(std::nullptr_t, const impl_ptr<T, D, C> &p)
422 inline bool operator>=(std::nullptr_t, const impl_ptr<T, D, C> &p)
419 {
423 {
420 return !(nullptr < p);
424 return !(nullptr < p);
421 }
425 }
422
426
423
427
424 template <class T, class... Args>
428 template <class T, class... Args>
425 inline impl_ptr<T> make_impl(Args &&... args)
429 inline impl_ptr<T> make_impl(Args &&... args)
426 {
430 {
427 return impl_ptr<T>(new T(std::forward<Args>(args)...), &details::default_delete<T>,
431 return impl_ptr<T>(new T(std::forward<Args>(args)...), &details::default_delete<T>,
428 &details::default_copy<T>);
432 &details::default_copy<T>);
429 }
433 }
430
434
431
435
432 // Helpers to manage unique impl, stored in std::unique_ptr
436 // Helpers to manage unique impl, stored in std::unique_ptr
433
437
434 template <class T, class Deleter = void (*)(T *)>
438 template <class T, class Deleter = void (*)(T *)>
435 using unique_impl_ptr = std::unique_ptr<T, Deleter>;
439 using unique_impl_ptr = std::unique_ptr<T, Deleter>;
436
440
437 template <class T, class... Args>
441 template <class T, class... Args>
438 inline unique_impl_ptr<T> make_unique_impl(Args &&... args)
442 inline unique_impl_ptr<T> make_unique_impl(Args &&... args)
439 {
443 {
440 static_assert(!std::is_array<T>::value, "unique_impl_ptr does not support arrays");
444 static_assert(!std::is_array<T>::value, "unique_impl_ptr does not support arrays");
441 return unique_impl_ptr<T>(new T(std::forward<Args>(args)...), &details::default_delete<T>);
445 return unique_impl_ptr<T>(new T(std::forward<Args>(args)...), &details::default_delete<T>);
442 }
446 }
443 }
447 }
444
448
445 namespace std {
449 namespace std {
446 template <class T, class D, class C>
450 template <class T, class D, class C>
447 struct hash<spimpl::impl_ptr<T, D, C> > {
451 struct hash<spimpl::impl_ptr<T, D, C> > {
448 using argument_type = spimpl::impl_ptr<T, D, C>;
452 using argument_type = spimpl::impl_ptr<T, D, C>;
449 using result_type = size_t;
453 using result_type = size_t;
450
454
451 result_type operator()(const argument_type &p) const SPIMPL_NOEXCEPT
455 result_type operator()(const argument_type &p) const SPIMPL_NOEXCEPT
452 {
456 {
453 return hash<typename argument_type::pointer>()(p.get());
457 return hash<typename argument_type::pointer>()(p.get());
454 }
458 }
455 };
459 };
456 }
460 }
457
461
458 #endif // SPIMPL_H_
462 #endif // SPIMPL_H_
General Comments 0
You need to be logged in to leave comments. Login now