]> git.lyx.org Git - lyx.git/blob - src/support/copied_ptr.h
1bf94d349abf8453517a20f52cc0918d8790c532
[lyx.git] / src / support / copied_ptr.h
1 // -*- C++ -*-
2 /**
3  * \file copied_ptr.h
4  * This file is part of LyX, the document processor.
5  * Licence details can be found in the file COPYING.
6  *
7  * \author Angus Leeming
8  *
9  * A templated class that can serve as a pointer to an object, with the
10  * property that when the copied_ptr is copied, it creates its own copy
11  * of the object pointed to as well.
12  *
13  * The implementation was based originally on Yonat Sharon's copied_ptr templated
14  * class, as described at http://ootips.org/yonat/, but has evolved toward's
15  * Herb Sutter's HolderPtr, as described at http://www.gotw.ca/gotw/062.htm.
16  * (Note, HolderPtr became ValuePtr in his book, More Exceptional C++.)
17  *
18  * Warning: if the class stores 'Base * ptr_', but the actual object pointed to
19  * belongs to a derived class, then you must specialise memory_traits<Base> so that
20  * its clone and destroy member functions do the right thing. Otherwise, you'll
21  * end up slicing the data.
22  */
23
24 #ifndef COPIED_PTR_H
25 #define COPIED_PTR_H
26
27 namespace lyx {
28 namespace support {
29
30 template <typename T>
31 struct memory_traits {
32         static T * clone(T const * ptr) { return new T(*ptr); }
33         static void destroy(T * ptr) { delete ptr; }
34 };
35
36
37 template <typename T, typename Traits=memory_traits<T> >
38 class copied_ptr {
39 public:
40         explicit copied_ptr(T * = 0);
41         copied_ptr(copied_ptr const &);
42         ~copied_ptr();
43         copied_ptr & operator=(copied_ptr const &);
44
45         T & operator*() const;
46         T * operator->() const;
47         T * get() const;
48
49 private:
50         T * ptr_;
51         void swap(copied_ptr &);
52 };
53
54
55 template <typename T, typename Traits>
56 copied_ptr<T, Traits>::copied_ptr(T * p)
57         : ptr_(p)
58 {}
59
60
61 template <typename T, typename Traits>
62 copied_ptr<T, Traits>::copied_ptr(copied_ptr const & other)
63         : ptr_(other.ptr_ ? Traits::clone(other.ptr_) : 0)
64 {}
65
66
67 template <typename T, typename Traits>
68 copied_ptr<T, Traits>::~copied_ptr()
69 {
70         Traits::destroy(ptr_);
71 }
72
73
74 template <typename T, typename Traits>
75 copied_ptr<T, Traits> & copied_ptr<T, Traits>::operator=(copied_ptr const & other)
76 {
77         if (&other != this) {
78                 copied_ptr temp(other);
79                 swap(temp);
80         }
81         return *this;
82 }
83
84
85 template <typename T, typename Traits>
86 T & copied_ptr<T, Traits>::operator*() const
87 {
88         return *ptr_;
89 }
90
91
92 template <typename T, typename Traits>
93 T * copied_ptr<T, Traits>::operator->() const
94 {
95         return ptr_;
96 }
97
98
99 template <typename T, typename Traits>
100 T * copied_ptr<T, Traits>::get() const
101 {
102         return ptr_;
103 }
104
105
106 template <typename T, typename Traits>
107 void copied_ptr<T, Traits>::swap(copied_ptr & other)
108 {
109         std::swap( ptr_, other.ptr_ );
110 }
111
112 } // namespace support
113 } // namespace lyx
114
115 #endif // NOT COPIED_PTR_H