• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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