Chris@16
|
1 // (C) Copyright Thorsten Ottosen 2005.
|
Chris@16
|
2 // (C) Copyright Jonathan Turkanis 2004.
|
Chris@16
|
3 // (C) Copyright Daniel Wallin 2004.
|
Chris@16
|
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
|
Chris@16
|
6
|
Chris@16
|
7 // Implementation of the move_ptr from the "Move Proposal"
|
Chris@101
|
8 // (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm)
|
Chris@16
|
9 // enhanced to support custom deleters and safe boolean conversions.
|
Chris@16
|
10 //
|
Chris@16
|
11 // The implementation is based on an implementation by Daniel Wallin, at
|
Chris@16
|
12 // "http://aspn.activestate.com/ASPN/Mail/Message/Attachments/boost/
|
Chris@16
|
13 // 400DC271.1060903@student.umu.se/move_ptr.hpp". The current was adapted
|
Chris@16
|
14 // by Jonathan Turkanis to incorporating ideas of Howard Hinnant and
|
Chris@16
|
15 // Rani Sharoni.
|
Chris@16
|
16
|
Chris@16
|
17 #ifndef BOOST_STATIC_MOVE_PTR_HPP_INCLUDED
|
Chris@16
|
18 #define BOOST_STATIC_MOVE_PTR_HPP_INCLUDED
|
Chris@16
|
19
|
Chris@16
|
20 #include <boost/config.hpp> // Member template friends, put size_t in std.
|
Chris@16
|
21 #include <cstddef> // size_t
|
Chris@16
|
22 #include <boost/compressed_pair.hpp>
|
Chris@16
|
23 #include <boost/ptr_container/detail/default_deleter.hpp>
|
Chris@16
|
24 #include <boost/ptr_container/detail/is_convertible.hpp>
|
Chris@16
|
25 #include <boost/ptr_container/detail/move.hpp>
|
Chris@16
|
26 #include <boost/static_assert.hpp>
|
Chris@16
|
27 #include <boost/type_traits/add_reference.hpp>
|
Chris@16
|
28 #include <boost/type_traits/is_array.hpp>
|
Chris@16
|
29
|
Chris@16
|
30 #if defined(BOOST_MSVC)
|
Chris@16
|
31 #pragma warning(push)
|
Chris@16
|
32 #pragma warning(disable:4521) // Multiple copy constuctors.
|
Chris@16
|
33 #endif
|
Chris@16
|
34
|
Chris@16
|
35 namespace boost { namespace ptr_container_detail {
|
Chris@16
|
36
|
Chris@16
|
37
|
Chris@16
|
38 template< typename T,
|
Chris@16
|
39 typename Deleter =
|
Chris@16
|
40 move_ptrs::default_deleter<T> >
|
Chris@16
|
41 class static_move_ptr
|
Chris@16
|
42 {
|
Chris@16
|
43 public:
|
Chris@16
|
44
|
Chris@16
|
45 typedef typename remove_bounds<T>::type element_type;
|
Chris@16
|
46 typedef Deleter deleter_type;
|
Chris@16
|
47
|
Chris@16
|
48 private:
|
Chris@16
|
49
|
Chris@16
|
50 struct safe_bool_helper { int x; };
|
Chris@16
|
51 typedef int safe_bool_helper::* safe_bool;
|
Chris@16
|
52 typedef boost::compressed_pair<element_type*, Deleter> impl_type;
|
Chris@16
|
53
|
Chris@16
|
54 public:
|
Chris@16
|
55 typedef typename impl_type::second_reference deleter_reference;
|
Chris@16
|
56 typedef typename impl_type::second_const_reference deleter_const_reference;
|
Chris@16
|
57
|
Chris@16
|
58 // Constructors
|
Chris@16
|
59
|
Chris@16
|
60 static_move_ptr() : impl_(0) { }
|
Chris@16
|
61
|
Chris@16
|
62 static_move_ptr(const static_move_ptr& p)
|
Chris@16
|
63 : impl_(p.get(), p.get_deleter())
|
Chris@16
|
64 {
|
Chris@16
|
65 const_cast<static_move_ptr&>(p).release();
|
Chris@16
|
66 }
|
Chris@16
|
67
|
Chris@16
|
68 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
Chris@16
|
69 static_move_ptr( const move_ptrs::move_source<static_move_ptr<T,Deleter> >& src )
|
Chris@16
|
70 #else
|
Chris@16
|
71 static_move_ptr( const move_ptrs::move_source<static_move_ptr>& src )
|
Chris@16
|
72 #endif
|
Chris@16
|
73 : impl_(src.ptr().get(), src.ptr().get_deleter())
|
Chris@16
|
74 {
|
Chris@16
|
75 src.ptr().release();
|
Chris@16
|
76 }
|
Chris@16
|
77
|
Chris@16
|
78 template<typename TT>
|
Chris@16
|
79 explicit static_move_ptr(TT* tt)
|
Chris@16
|
80 : impl_(tt, Deleter())
|
Chris@16
|
81 { }
|
Chris@16
|
82
|
Chris@16
|
83 // Destructor
|
Chris@16
|
84
|
Chris@16
|
85 ~static_move_ptr() { if (ptr()) get_deleter()(ptr()); }
|
Chris@16
|
86
|
Chris@16
|
87 // Assignment
|
Chris@16
|
88
|
Chris@16
|
89 static_move_ptr& operator=(static_move_ptr rhs)
|
Chris@16
|
90 {
|
Chris@16
|
91 rhs.swap(*this);
|
Chris@16
|
92 return *this;
|
Chris@16
|
93 }
|
Chris@16
|
94
|
Chris@16
|
95 // Smart pointer interface
|
Chris@16
|
96
|
Chris@16
|
97 element_type* get() const { return ptr(); }
|
Chris@16
|
98
|
Chris@16
|
99 element_type& operator*()
|
Chris@16
|
100 {
|
Chris@16
|
101 /*BOOST_STATIC_ASSERT(!is_array);*/ return *ptr();
|
Chris@16
|
102 }
|
Chris@16
|
103
|
Chris@16
|
104 const element_type& operator*() const
|
Chris@16
|
105 {
|
Chris@16
|
106 /*BOOST_STATIC_ASSERT(!is_array);*/ return *ptr();
|
Chris@16
|
107 }
|
Chris@16
|
108
|
Chris@16
|
109 element_type* operator->()
|
Chris@16
|
110 {
|
Chris@16
|
111 /*BOOST_STATIC_ASSERT(!is_array);*/ return ptr();
|
Chris@16
|
112 }
|
Chris@16
|
113
|
Chris@16
|
114 const element_type* operator->() const
|
Chris@16
|
115 {
|
Chris@16
|
116 /*BOOST_STATIC_ASSERT(!is_array);*/ return ptr();
|
Chris@16
|
117 }
|
Chris@16
|
118
|
Chris@16
|
119
|
Chris@16
|
120 element_type* release()
|
Chris@16
|
121 {
|
Chris@16
|
122 element_type* result = ptr();
|
Chris@16
|
123 ptr() = 0;
|
Chris@16
|
124 return result;
|
Chris@16
|
125 }
|
Chris@16
|
126
|
Chris@16
|
127 void reset()
|
Chris@16
|
128 {
|
Chris@16
|
129 if (ptr()) get_deleter()(ptr());
|
Chris@16
|
130 ptr() = 0;
|
Chris@16
|
131 }
|
Chris@16
|
132
|
Chris@16
|
133 template<typename TT>
|
Chris@16
|
134 void reset(TT* tt)
|
Chris@16
|
135 {
|
Chris@16
|
136 static_move_ptr(tt).swap(*this);
|
Chris@16
|
137 }
|
Chris@16
|
138
|
Chris@16
|
139 template<typename TT, typename DD>
|
Chris@16
|
140 void reset(TT* tt, DD dd)
|
Chris@16
|
141 {
|
Chris@16
|
142 static_move_ptr(tt, dd).swap(*this);
|
Chris@16
|
143 }
|
Chris@16
|
144
|
Chris@16
|
145 operator safe_bool() const { return ptr() ? &safe_bool_helper::x : 0; }
|
Chris@16
|
146
|
Chris@16
|
147 void swap(static_move_ptr& p) { impl_.swap(p.impl_); }
|
Chris@16
|
148
|
Chris@16
|
149 deleter_reference get_deleter() { return impl_.second(); }
|
Chris@16
|
150
|
Chris@16
|
151 deleter_const_reference get_deleter() const { return impl_.second(); }
|
Chris@16
|
152 private:
|
Chris@16
|
153 template<typename TT, typename DD>
|
Chris@16
|
154 void check(const static_move_ptr<TT, DD>& ptr)
|
Chris@16
|
155 {
|
Chris@16
|
156 typedef move_ptrs::is_smart_ptr_convertible<TT, T> convertible;
|
Chris@16
|
157 BOOST_STATIC_ASSERT(convertible::value);
|
Chris@16
|
158 }
|
Chris@16
|
159
|
Chris@16
|
160 #if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || defined(BOOST_NO_SFINAE)
|
Chris@16
|
161 // give up on this behavior
|
Chris@16
|
162 #else
|
Chris@16
|
163
|
Chris@16
|
164 template<typename Ptr> struct cant_move_from_const;
|
Chris@16
|
165
|
Chris@16
|
166 template<typename TT, typename DD>
|
Chris@16
|
167 struct cant_move_from_const< const static_move_ptr<TT, DD> > {
|
Chris@16
|
168 typedef typename static_move_ptr<TT, DD>::error type;
|
Chris@16
|
169 };
|
Chris@16
|
170
|
Chris@16
|
171 template<typename Ptr>
|
Chris@16
|
172 static_move_ptr(Ptr&, typename cant_move_from_const<Ptr>::type = 0);
|
Chris@16
|
173
|
Chris@16
|
174
|
Chris@16
|
175 public:
|
Chris@16
|
176 static_move_ptr(static_move_ptr&);
|
Chris@16
|
177
|
Chris@16
|
178
|
Chris@16
|
179 private:
|
Chris@16
|
180 template<typename TT, typename DD>
|
Chris@16
|
181 static_move_ptr( static_move_ptr<TT, DD>&,
|
Chris@16
|
182 typename
|
Chris@16
|
183 move_ptrs::enable_if_convertible<
|
Chris@16
|
184 TT, T, static_move_ptr&
|
Chris@16
|
185 >::type::type* = 0 );
|
Chris@16
|
186
|
Chris@16
|
187 #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING || BOOST_NO_SFINAE
|
Chris@16
|
188
|
Chris@16
|
189 //#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
|
Chris@16
|
190 // template<typename TT, typename DD>
|
Chris@16
|
191 // friend class static_move_ptr;
|
Chris@16
|
192 //#else
|
Chris@16
|
193 public:
|
Chris@16
|
194 //#endif
|
Chris@16
|
195 typename impl_type::first_reference
|
Chris@16
|
196 ptr() { return impl_.first(); }
|
Chris@16
|
197
|
Chris@16
|
198 typename impl_type::first_const_reference
|
Chris@16
|
199 ptr() const { return impl_.first(); }
|
Chris@16
|
200
|
Chris@16
|
201 impl_type impl_;
|
Chris@16
|
202 };
|
Chris@16
|
203
|
Chris@16
|
204 } // namespace ptr_container_detail
|
Chris@16
|
205 } // End namespace boost.
|
Chris@16
|
206
|
Chris@16
|
207 #if defined(BOOST_MSVC)
|
Chris@16
|
208 #pragma warning(pop) // #pragma warning(disable:4251)
|
Chris@16
|
209 #endif
|
Chris@16
|
210
|
Chris@16
|
211 #endif // #ifndef BOOST_STATIC_MOVE_PTR_HPP_INCLUDED
|