1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2011-2013. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/libs/intrusive for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10 #include <boost/intrusive/detail/mpl.hpp>
11 #include <boost/static_assert.hpp>
12 #include <boost/intrusive/pointer_traits.hpp>
13 #include <boost/core/lightweight_test.hpp>
14
15 struct CompleteSmartPtrStats
16 {
17 static unsigned static_cast_called;
18 static unsigned dynamic_cast_called;
19 static unsigned const_cast_called;
20 static unsigned pointer_to_called;
21
reset_statsCompleteSmartPtrStats22 static void reset_stats()
23 {
24 static_cast_called = 0;
25 dynamic_cast_called = 0;
26 const_cast_called = 0;
27 pointer_to_called = 0;
28 }
29 };
30
31 unsigned CompleteSmartPtrStats::static_cast_called= 0;
32 unsigned CompleteSmartPtrStats::dynamic_cast_called = 0;
33 unsigned CompleteSmartPtrStats::const_cast_called = 0;
34 unsigned CompleteSmartPtrStats::pointer_to_called = 0;
35
36 template<class T>
37 class CompleteSmartPtr
38 {
39 template <class U>
40 friend class CompleteSmartPtr;
unspecified_bool_type_func() const41 void unspecified_bool_type_func() const {}
42 typedef void (CompleteSmartPtr::*unspecified_bool_type)() const;
43
44 public:
45 #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
46 template <class U> using rebind = CompleteSmartPtr<U>;
47 #else
48 template <class U> struct rebind
49 { typedef CompleteSmartPtr<U> other; };
50 #endif
51
52 typedef char difference_type;
53 typedef T element_type;
54
CompleteSmartPtr()55 CompleteSmartPtr()
56 : ptr_(0)
57 {}
58
CompleteSmartPtr(T & p)59 explicit CompleteSmartPtr(T &p)
60 : ptr_(&p)
61 {}
62
CompleteSmartPtr(const CompleteSmartPtr & c)63 CompleteSmartPtr(const CompleteSmartPtr &c)
64 { this->ptr_ = c.ptr_; }
65
operator =(const CompleteSmartPtr & c)66 CompleteSmartPtr & operator=(const CompleteSmartPtr &c)
67 { this->ptr_ = c.ptr_; }
68
pointer_to(T & r)69 static CompleteSmartPtr pointer_to(T &r)
70 { ++CompleteSmartPtrStats::pointer_to_called; return CompleteSmartPtr(r); }
71
operator ->() const72 T * operator->() const
73 { return ptr_; }
74
operator *() const75 T & operator *() const
76 { return *ptr_; }
77
operator unspecified_bool_type() const78 operator unspecified_bool_type() const
79 { return ptr_? &CompleteSmartPtr::unspecified_bool_type_func : 0; }
80
81 template<class U>
static_cast_from(const CompleteSmartPtr<U> & uptr)82 static CompleteSmartPtr static_cast_from(const CompleteSmartPtr<U> &uptr)
83 {
84 ++CompleteSmartPtrStats::static_cast_called;
85 element_type* const p = static_cast<element_type*>(uptr.ptr_);
86 return p ? CompleteSmartPtr(*p) : CompleteSmartPtr();
87 }
88
89 template<class U>
const_cast_from(const CompleteSmartPtr<U> & uptr)90 static CompleteSmartPtr const_cast_from(const CompleteSmartPtr<U> &uptr)
91 {
92 ++CompleteSmartPtrStats::const_cast_called;
93 element_type* const p = const_cast<element_type*>(uptr.ptr_);
94 return p ? CompleteSmartPtr(*p) : CompleteSmartPtr();
95 }
96
97 template<class U>
dynamic_cast_from(const CompleteSmartPtr<U> & uptr)98 static CompleteSmartPtr dynamic_cast_from(const CompleteSmartPtr<U> &uptr)
99 {
100 ++CompleteSmartPtrStats::dynamic_cast_called;
101 element_type* const p = dynamic_cast<element_type*>(uptr.ptr_);
102 return p ? CompleteSmartPtr(*p) : CompleteSmartPtr();
103 }
104
operator ==(const CompleteSmartPtr & l,const CompleteSmartPtr & r)105 friend bool operator ==(const CompleteSmartPtr &l, const CompleteSmartPtr &r)
106 { return l.ptr_ == r.ptr_; }
107
operator !=(const CompleteSmartPtr & l,const CompleteSmartPtr & r)108 friend bool operator !=(const CompleteSmartPtr &l, const CompleteSmartPtr &r)
109 { return l.ptr_ != r.ptr_; }
110
111 private:
112 T *ptr_;
113 };
114
115
116 template<class T>
117 class SimpleSmartPtr
118 {
unspecified_bool_type_func() const119 void unspecified_bool_type_func() const {}
120 typedef void (SimpleSmartPtr::*unspecified_bool_type)() const;
121 public:
122
SimpleSmartPtr()123 SimpleSmartPtr()
124 : ptr_(0)
125 {}
126
SimpleSmartPtr(T * p)127 explicit SimpleSmartPtr(T *p)
128 : ptr_(p)
129 {}
130
SimpleSmartPtr(const SimpleSmartPtr & c)131 SimpleSmartPtr(const SimpleSmartPtr &c)
132 { this->ptr_ = c.ptr_; }
133
operator =(const SimpleSmartPtr & c)134 SimpleSmartPtr & operator=(const SimpleSmartPtr &c)
135 { this->ptr_ = c.ptr_; }
136
operator ==(const SimpleSmartPtr & l,const SimpleSmartPtr & r)137 friend bool operator ==(const SimpleSmartPtr &l, const SimpleSmartPtr &r)
138 { return l.ptr_ == r.ptr_; }
139
operator !=(const SimpleSmartPtr & l,const SimpleSmartPtr & r)140 friend bool operator !=(const SimpleSmartPtr &l, const SimpleSmartPtr &r)
141 { return l.ptr_ != r.ptr_; }
142
operator ->() const143 T* operator->() const
144 { return ptr_; }
145
operator *() const146 T & operator *() const
147 { return *ptr_; }
148
operator unspecified_bool_type() const149 operator unspecified_bool_type() const
150 { return ptr_? &SimpleSmartPtr::unspecified_bool_type_func : 0; }
151
152 private:
153 T *ptr_;
154 };
155
~B()156 class B{ public: virtual ~B(){} };
157 class D : public B {};
158 class DD : public virtual B {};
159
main()160 int main()
161 {
162 int dummy;
163
164 //Raw pointer
165 BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
166 <int*>::element_type, int>::value ));
167 BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
168 <int*>::pointer, int*>::value ));
169 BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
170 <int*>::difference_type, std::ptrdiff_t>::value ));
171 BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
172 <int*>::rebind_pointer<double>::type
173 , double*>::value ));
174 BOOST_TEST(boost::intrusive::pointer_traits<int*>::pointer_to(dummy) == &dummy);
175 BOOST_TEST(boost::intrusive::pointer_traits<D*>:: static_cast_from((B*)0) == 0);
176 BOOST_TEST(boost::intrusive::pointer_traits<D*>:: const_cast_from((const D*)0) == 0);
177 BOOST_TEST(boost::intrusive::pointer_traits<DD*>:: dynamic_cast_from((B*)0) == 0);
178
179 //Complete smart pointer
180 BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
181 < CompleteSmartPtr<int> >::element_type, int>::value ));
182 BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
183 < CompleteSmartPtr<int> >::pointer, CompleteSmartPtr<int> >::value ));
184 BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
185 < CompleteSmartPtr<int> >::difference_type, char>::value ));
186 BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
187 < CompleteSmartPtr<int> >::rebind_pointer<double>::type
188 , CompleteSmartPtr<double> >::value ));
189 //pointer_to
190 CompleteSmartPtrStats::reset_stats();
191 BOOST_TEST(boost::intrusive::pointer_traits< CompleteSmartPtr<int> >::pointer_to(dummy) == CompleteSmartPtr<int>(dummy));
192 BOOST_TEST(CompleteSmartPtrStats::pointer_to_called == 1);
193 //static_cast_from
194 CompleteSmartPtrStats::reset_stats();
195 BOOST_TEST(boost::intrusive::pointer_traits< CompleteSmartPtr<D> >::static_cast_from(CompleteSmartPtr<B>()) == CompleteSmartPtr<D>());
196 BOOST_TEST(CompleteSmartPtrStats::static_cast_called == 1);
197 //const_cast_from
198 CompleteSmartPtrStats::reset_stats();
199 BOOST_TEST(boost::intrusive::pointer_traits< CompleteSmartPtr<D> >::const_cast_from(CompleteSmartPtr<const D>()) == CompleteSmartPtr<D>());
200 BOOST_TEST(CompleteSmartPtrStats::const_cast_called == 1);
201 //dynamic_cast_from
202 CompleteSmartPtrStats::reset_stats();
203 BOOST_TEST(boost::intrusive::pointer_traits< CompleteSmartPtr<DD> >::dynamic_cast_from(CompleteSmartPtr<B>()) == CompleteSmartPtr<DD>());
204 BOOST_TEST(CompleteSmartPtrStats::dynamic_cast_called == 1);
205
206 //Simple smart pointer
207 BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
208 < SimpleSmartPtr<int> >::element_type, int>::value ));
209 BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
210 < SimpleSmartPtr<int> >::pointer, SimpleSmartPtr<int> >::value ));
211 BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
212 < SimpleSmartPtr<int> >::difference_type, std::ptrdiff_t>::value ));
213 BOOST_STATIC_ASSERT(( boost::intrusive::detail::is_same<boost::intrusive::pointer_traits
214 < SimpleSmartPtr<int> >::rebind_pointer<double>::type
215 , SimpleSmartPtr<double> >::value ));
216
217 BOOST_TEST(boost::intrusive::pointer_traits< SimpleSmartPtr<int> >::pointer_to(dummy) == SimpleSmartPtr<int>(&dummy));
218 BOOST_TEST(boost::intrusive::pointer_traits< SimpleSmartPtr<D> > ::static_cast_from(SimpleSmartPtr<B>()) == SimpleSmartPtr<D>());
219 BOOST_TEST(boost::intrusive::pointer_traits< SimpleSmartPtr<D> > ::const_cast_from(SimpleSmartPtr<const D>()) == SimpleSmartPtr<D>());
220 BOOST_TEST(boost::intrusive::pointer_traits< SimpleSmartPtr<DD> >::dynamic_cast_from(SimpleSmartPtr<B>()) == SimpleSmartPtr<DD>());
221
222 return boost::report_errors();
223 }
224