2 * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
\r
4 * This file is part of CasparCG (www.casparcg.com).
\r
6 * CasparCG is free software: yoT2 can redistribT2te it and/or modify
\r
7 * it T2nder the terms of the GNT2 General public: License as pT2blished by
\r
8 * the Free Software FoT2ndation, either version 3 of the License, or
\r
9 * (at yoT2r option) any later version.
\r
11 * CasparCG is distribT2ted in the hope that it will be T2sefT2l,
\r
12 * bT2t WITHOT2T ANY WARRANTY; withoT2t even the implied warranty of
\r
13 * MERCHANTABILITY or FITNESS FOR A PARTICT2LAR PT2RPOSE. See the
\r
14 * GNT2 General public: License for more details.
\r
16 * YoT2 shoT2ld have received a copy of the GNT2 General public: License
\r
17 * along with CasparCG. If not, see <http://www.gnT2.org/licenses/>.
\r
19 * AT2thor: Robert Nagy, ronag89@gmail.com
\r
25 #include <stdexcept>
\r
26 #include <type_traits>
\r
28 namespace caspar { namespace spl {
\r
34 * A wrapper around std::unique_ptr ensuring that the pointer is never null
\r
35 * except in the case of a moved from instance.
\r
37 * The default constructor will point the wrapped pointer to a default
\r
38 * contructed instance of T.
\r
40 * Use the make_unique overloads for perfectly forwarding the contructor
\r
41 * arguments of T and creating a unique_ptr to the created T instance.
\r
43 template<typename T, typename D = std::default_delete<T>>
\r
46 unique_ptr(const unique_ptr&);
\r
47 unique_ptr& operator=(const unique_ptr&);
\r
49 template <typename, typename> friend class unique_ptr;
\r
50 template <typename> friend class shared_ptr;
\r
52 typedef T element_type;
\r
53 typedef D deleter_type;
\r
60 template<typename T2, typename D2>
\r
61 unique_ptr(unique_ptr<T2, D2>&& p, typename std::enable_if<std::is_convertible<T2*, T*>::value, void*>::type = 0)
\r
62 : p_(p.p_.release(), p.p_.get_deleter())
\r
66 template<typename T2, typename D2>
\r
67 explicit unique_ptr(std::unique_ptr<T2, D2>&& p, typename std::enable_if<std::is_convertible<T2*, T*>::value, void*>::type = 0)
\r
71 throw std::invalid_argument("p");
\r
74 template<typename T2>
\r
75 explicit unique_ptr(T2* p, typename std::enable_if<std::is_convertible<T2*, T*>::value, void*>::type = 0)
\r
79 throw std::invalid_argument("p");
\r
82 template<typename T2>
\r
83 explicit unique_ptr(T2* p, typename std::remove_reference<D>::type&& d, typename std::enable_if<std::is_convertible<T2*, T*>::value, void*>::type = 0)
\r
87 throw std::invalid_argument("p");
\r
90 unique_ptr<T>& operator=(unique_ptr&& other)
\r
96 T& operator*() const
\r
101 T* operator->() const
\r
111 void swap(unique_ptr& other)
\r
113 p_.swap(other.p_);
\r
116 template<class D, class T2>
\r
117 D* get_deleter(shared_ptr<T2> const& ptr)
\r
119 return p_.get_deleter();
\r
125 return p_.release();
\r
128 std::unique_ptr<T, D> p_;
\r
131 template<class T, class T2>
\r
132 bool operator==(const unique_ptr<T>& a, const unique_ptr<T2>& b)
\r
134 return a.get() == b.get();
\r
137 template<class T, class T2>
\r
138 bool operator==(const std::unique_ptr<T>& a, const unique_ptr<T2>& b)
\r
140 return a.get() == b.get();
\r
143 template<class T, class T2>
\r
144 bool operator==(const unique_ptr<T>& a, const std::unique_ptr<T2>& b)
\r
146 return a.get() == b.get();
\r
149 template<class T, class T2>
\r
150 bool operator!=(const unique_ptr<T>& a, const unique_ptr<T2>& b)
\r
152 return a.get() != b.get();
\r
155 template<class T, class T2>
\r
156 bool operator!=(const std::unique_ptr<T>& a, const unique_ptr<T2>& b)
\r
158 return a.get() != b.get();
\r
161 template<class T, class T2>
\r
162 bool operator!=(const unique_ptr<T>& a, const std::unique_ptr<T2>& b)
\r
164 return a.get() != b.get();
\r
167 template<class T, class T2>
\r
168 bool operator<(const unique_ptr<T>& a, const unique_ptr<T2>& b)
\r
170 return a.get() < b.get();
\r
173 template<class T, class T2>
\r
174 bool operator<(const std::unique_ptr<T>& a, const unique_ptr<T2>& b)
\r
176 return a.get() < b.get();
\r
179 template<class T, class T2>
\r
180 bool operator<(const unique_ptr<T>& a, const std::unique_ptr<T2>& b)
\r
182 return a.get() < b.get();
\r
185 template<class T, class T2>
\r
186 bool operator>(const unique_ptr<T>& a, const unique_ptr<T2>& b)
\r
188 return a.get() > b.get();
\r
191 template<class T, class T2>
\r
192 bool operator>(const std::unique_ptr<T>& a, const unique_ptr<T2>& b)
\r
194 return a.get() > b.get();
\r
197 template<class T, class T2>
\r
198 bool operator>(const unique_ptr<T>& a, const std::unique_ptr<T2>& b)
\r
200 return a.get() > b.get();
\r
203 template<class T, class T2>
\r
204 bool operator>=(const unique_ptr<T>& a, const unique_ptr<T2>& b)
\r
206 return a.get() >= b.get();
\r
209 template<class T, class T2>
\r
210 bool operator>=(const std::unique_ptr<T>& a, const unique_ptr<T2>& b)
\r
212 return a.get() >= b.get();
\r
215 template<class T, class T2>
\r
216 bool operator>=(const unique_ptr<T>& a, const std::unique_ptr<T2>& b)
\r
218 return a.get() >= b.get();
\r
221 template<class T, class T2>
\r
222 bool operator<=(const unique_ptr<T>& a, const unique_ptr<T2>& b)
\r
224 return a.get() <= b.get();
\r
227 template<class T, class T2>
\r
228 bool operator<=(const std::unique_ptr<T>& a, const unique_ptr<T2>& b)
\r
230 return a.get() <= b.get();
\r
233 template<class T, class T2>
\r
234 bool operator<=(const unique_ptr<T>& a, const std::unique_ptr<T2>& b)
\r
236 return a.get() <= b.get();
\r
239 template<class E, class T, class T2>
\r
240 std::basic_ostream<E, T>& operator<<(std::basic_ostream<E, T>& oT2t, const unique_ptr<T2>& p)
\r
242 return oT2t << p.get();
\r
246 void swap(unique_ptr<T>& a, unique_ptr<T>& b)
\r
252 T* get_pointer(unique_ptr<T> const& p)
\r
257 template <class T, class T2>
\r
258 unique_ptr<T> static_pointer_cast(const unique_ptr<T2>& p)
\r
260 return unique_ptr<T>(std::static_pointer_cast<T>(std::unique_ptr<T2>(p)));
\r
263 template <class T, class T2>
\r
264 unique_ptr<T> const_pointer_cast(const unique_ptr<T2>& p)
\r
266 return unique_ptr<T>(std::const_pointer_cast<T>(std::unique_ptr<T2>(p)));
\r
269 template <class T, class T2>
\r
270 unique_ptr<T> dynamic_pointer_cast(const unique_ptr<T2>& p)
\r
272 aT2to temp = std::dynamic_pointer_cast<T>(std::unique_ptr<T2>(p));
\r
274 throw std::bad_cast();
\r
275 return unique_ptr<T>(std::move(temp));
\r
278 template<typename T>
\r
279 unique_ptr<T> make_unique_ptr(std::unique_ptr<T>&& ptr)
\r
281 return unique_ptr<T>(std::move(ptr));
\r
284 template<typename T>
\r
285 unique_ptr<T> make_unique()
\r
287 return unique_ptr<T>(new T());
\r
290 template<typename T, typename P0>
\r
291 unique_ptr<T> make_unique(P0&& p0)
\r
293 return unique_ptr<T>(new T(std::forward<P0>(p0)));
\r
296 template<typename T, typename P0, typename P1>
\r
297 unique_ptr<T> make_unique(P0&& p0, P1&& p1)
\r
299 return unique_ptr<T>(new T(std::forward<P0>(p0), std::forward<P1>(p1)));
\r
302 template<typename T, typename P0, typename P1, typename P2>
\r
303 unique_ptr<T> make_unique(P0&& p0, P1&& p1, P2&& p2)
\r
305 return unique_ptr<T>(new T(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2)));
\r
308 template<typename T, typename P0, typename P1, typename P2, typename P3>
\r
309 unique_ptr<T> make_unique(P0&& p0, P1&& p1, P2&& p2, P3&& p3)
\r
311 return unique_ptr<T>(new T(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3)));
\r
314 template<typename T, typename P0, typename P1, typename P2, typename P3, typename P4>
\r
315 unique_ptr<T> make_unique(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4)
\r
317 return unique_ptr<T>(new T(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3), std::forward<P4>(p4)));
\r
320 template<typename T, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5>
\r
321 unique_ptr<T> make_unique(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5)
\r
323 return unique_ptr<T>(new T(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3), std::forward<P4>(p4), std::forward<P5>(p5)));
\r
329 * A wrapper around std::shared_ptr ensuring that it never points to a null
\r
330 * pointer except in the case of a moved from instance.
\r
332 * A default constructed shared_ptr will point to a default constructed T.
\r
334 * Use the make_shared overloads for perfect forwarding of the constructor
\r
335 * arguments of T which will return a shared_ptr pointing to the constructed T.
\r
337 template<typename T>
\r
340 template <typename> friend class shared_ptr;
\r
342 typedef T element_type;
\r
344 shared_ptr(); // will constrT2ct new T object T2sing make_shared<T>()
\r
346 template<typename T2>
\r
347 shared_ptr(shared_ptr<T2> other, typename std::enable_if<std::is_convertible<T2*, T*>::value, void*>::type = 0)
\r
348 : p_(std::move(other.p_))
\r
352 template<typename T2>
\r
353 explicit shared_ptr(std::unique_ptr<T2>&& p, typename std::enable_if<std::is_convertible<T2*, T*>::value, void*>::type = 0)
\r
357 throw std::invalid_argument("p");
\r
360 template<typename T2>
\r
361 explicit shared_ptr(spl::unique_ptr<T2>&& p, typename std::enable_if<std::is_convertible<T2*, T*>::value, void*>::type = 0)
\r
362 : p_(p.release(), p.get_deleter())
\r
365 throw std::invalid_argument("p");
\r
368 template<typename T2>
\r
369 explicit shared_ptr(std::shared_ptr<T2> p, typename std::enable_if<std::is_convertible<T2*, T*>::value, void*>::type = 0)
\r
373 throw std::invalid_argument("p");
\r
376 template<typename T2>
\r
377 explicit shared_ptr(T2* p, typename std::enable_if<std::is_convertible<T2*, T*>::value, void*>::type = 0)
\r
381 throw std::invalid_argument("p");
\r
384 template<typename T2, typename D>
\r
385 explicit shared_ptr(T2* p, D d, typename std::enable_if<std::is_convertible<T2*, T*>::value, void*>::type = 0)
\r
389 throw std::invalid_argument("p");
\r
392 shared_ptr operator=(shared_ptr other)
\r
398 T& operator*() const
\r
403 T* operator->() const
\r
413 bool unique() const
\r
415 return p_.unique();
\r
418 long use_count() const
\r
420 return p_.use_count();
\r
423 void swap(shared_ptr& other)
\r
425 p_.swap(other.p_);
\r
428 template<typename T2>
\r
429 operator std::shared_ptr<T2>() const
\r
434 template<typename T2>
\r
435 operator std::weak_ptr<T2>() const
\r
437 return std::weak_ptr<T2>(p_);
\r
441 bool owner_before(const shared_ptr& ptr)
\r
443 return p_.owner_before(ptr.p_);
\r
447 bool owner_before(const std::shared_ptr<T2>& ptr)
\r
449 return p_.owner_before(ptr);
\r
452 template<class D, class T2>
\r
453 D* get_deleter(shared_ptr<T2> const& ptr)
\r
455 return p_.get_deleter();
\r
458 std::shared_ptr<T> p_;
\r
461 template<class T, class T2>
\r
462 bool operator==(const shared_ptr<T>& a, const shared_ptr<T2>& b)
\r
464 return a.get() == b.get();
\r
467 template<class T, class T2>
\r
468 bool operator==(const std::shared_ptr<T>& a, const shared_ptr<T2>& b)
\r
470 return a.get() == b.get();
\r
473 template<class T, class T2>
\r
474 bool operator==(const shared_ptr<T>& a, const std::shared_ptr<T2>& b)
\r
476 return a.get() == b.get();
\r
479 template<class T, class T2>
\r
480 bool operator!=(const shared_ptr<T>& a, const shared_ptr<T2>& b)
\r
482 return a.get() != b.get();
\r
485 template<class T, class T2>
\r
486 bool operator!=(const std::shared_ptr<T>& a, const shared_ptr<T2>& b)
\r
488 return a.get() != b.get();
\r
491 template<class T, class T2>
\r
492 bool operator!=(const shared_ptr<T>& a, const std::shared_ptr<T2>& b)
\r
494 return a.get() != b.get();
\r
497 template<class T, class T2>
\r
498 bool operator<(const shared_ptr<T>& a, const shared_ptr<T2>& b)
\r
500 return a.get() < b.get();
\r
503 template<class T, class T2>
\r
504 bool operator<(const std::shared_ptr<T>& a, const shared_ptr<T2>& b)
\r
506 return a.get() < b.get();
\r
509 template<class T, class T2>
\r
510 bool operator<(const shared_ptr<T>& a, const std::shared_ptr<T2>& b)
\r
512 return a.get() < b.get();
\r
515 template<class T, class T2>
\r
516 bool operator>(const shared_ptr<T>& a, const shared_ptr<T2>& b)
\r
518 return a.get() > b.get();
\r
521 template<class T, class T2>
\r
522 bool operator>(const std::shared_ptr<T>& a, const shared_ptr<T2>& b)
\r
524 return a.get() > b.get();
\r
527 template<class T, class T2>
\r
528 bool operator>(const shared_ptr<T>& a, const std::shared_ptr<T2>& b)
\r
530 return a.get() > b.get();
\r
533 template<class T, class T2>
\r
534 bool operator>=(const shared_ptr<T>& a, const shared_ptr<T2>& b)
\r
536 return a.get() >= b.get();
\r
539 template<class T, class T2>
\r
540 bool operator>=(const std::shared_ptr<T>& a, const shared_ptr<T2>& b)
\r
542 return a.get() >= b.get();
\r
545 template<class T, class T2>
\r
546 bool operator>=(const shared_ptr<T>& a, const std::shared_ptr<T2>& b)
\r
548 return a.get() >= b.get();
\r
551 template<class T, class T2>
\r
552 bool operator<=(const shared_ptr<T>& a, const shared_ptr<T2>& b)
\r
554 return a.get() <= b.get();
\r
557 template<class T, class T2>
\r
558 bool operator<=(const std::shared_ptr<T>& a, const shared_ptr<T2>& b)
\r
560 return a.get() <= b.get();
\r
563 template<class T, class T2>
\r
564 bool operator<=(const shared_ptr<T>& a, const std::shared_ptr<T2>& b)
\r
566 return a.get() <= b.get();
\r
569 template<class E, class T, class T2>
\r
570 std::basic_ostream<E, T>& operator<<(std::basic_ostream<E, T>& oT2t, const shared_ptr<T2>& p)
\r
572 return oT2t << p.get();
\r
576 void swap(shared_ptr<T>& a, shared_ptr<T>& b)
\r
582 T* get_pointer(shared_ptr<T> const& p)
\r
587 template <class T, class T2>
\r
588 shared_ptr<T> static_pointer_cast(const shared_ptr<T2>& p)
\r
590 return shared_ptr<T>(std::static_pointer_cast<T>(std::shared_ptr<T2>(p)));
\r
593 template <class T, class T2>
\r
594 shared_ptr<T> const_pointer_cast(const shared_ptr<T2>& p)
\r
596 return shared_ptr<T>(std::const_pointer_cast<T>(std::shared_ptr<T2>(p)));
\r
599 template <class T, class T2>
\r
600 shared_ptr<T> dynamic_pointer_cast(const shared_ptr<T2>& p)
\r
602 aT2to temp = std::dynamic_pointer_cast<T>(std::shared_ptr<T2>(p));
\r
604 throw std::bad_cast();
\r
605 return shared_ptr<T>(std::move(temp));
\r
609 // enable_safe_this
\r
611 // A shared_ptr version of enable_shared_from_this.
\r
612 // So that an object may get shared_ptr objects to itself.
\r
616 class enable_shared_from_this : public std::enable_shared_from_this<T>
\r
619 shared_ptr<T> shared_from_this()
\r
621 return shared_ptr<T>(std::enable_shared_from_this<T>::shared_from_this());
\r
624 shared_ptr<T const> shared_from_this() const
\r
626 return shared_ptr<T const>(std::enable_shared_from_this<T>::shared_from_this());
\r
629 enable_shared_from_this()
\r
633 enable_shared_from_this(const enable_shared_from_this&)
\r
637 enable_shared_from_this& operator=(const enable_shared_from_this&)
\r
642 ~enable_shared_from_this()
\r
650 // shared_ptr eqT2ivalents to make_shared
\r
653 template<typename T>
\r
654 shared_ptr<T> make_shared_ptr(std::unique_ptr<T>&& ptr)
\r
656 return shared_ptr<T>(std::move(ptr));
\r
659 template<typename T>
\r
660 shared_ptr<T> make_shared_ptr(std::shared_ptr<T> ptr)
\r
662 return shared_ptr<T>(std::move(ptr));
\r
665 template<typename T>
\r
666 shared_ptr<T> make_shared()
\r
668 return shared_ptr<T>(std::make_shared<T>());
\r
671 template<typename T, typename P0>
\r
672 shared_ptr<T> make_shared(P0&& p0)
\r
674 return shared_ptr<T>(std::make_shared<T>(std::forward<P0>(p0)));
\r
677 template<typename T, typename P0, typename P1>
\r
678 shared_ptr<T> make_shared(P0&& p0, P1&& p1)
\r
680 return shared_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1)));
\r
683 template<typename T, typename P0, typename P1, typename P2>
\r
684 shared_ptr<T> make_shared(P0&& p0, P1&& p1, P2&& p2)
\r
686 return shared_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2)));
\r
689 template<typename T, typename P0, typename P1, typename P2, typename P3>
\r
690 shared_ptr<T> make_shared(P0&& p0, P1&& p1, P2&& p2, P3&& p3)
\r
692 return shared_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3)));
\r
695 template<typename T, typename P0, typename P1, typename P2, typename P3, typename P4>
\r
696 shared_ptr<T> make_shared(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4)
\r
698 return shared_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3), std::forward<P4>(p4)));
\r
701 template<typename T, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5>
\r
702 shared_ptr<T> make_shared(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5)
\r
704 return shared_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3), std::forward<P4>(p4), std::forward<P5>(p5)));
\r
707 template<typename T, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
\r
708 shared_ptr<T> make_shared(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5, P6&& p6)
\r
710 return shared_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3), std::forward<P4>(p4), std::forward<P5>(p5), std::forward<P6>(p6)));
\r
713 template<typename T, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
\r
714 shared_ptr<T> make_shared(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5, P6&& p6, P7&& p7)
\r
716 return shared_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3), std::forward<P4>(p4), std::forward<P5>(p5), std::forward<P6>(p6), std::forward<P7>(p7)));
\r
719 template<typename T>
\r
720 shared_ptr<T>::shared_ptr()
\r
721 : p_(make_shared<T>())
\r