Revert "Quick fix to allow PK and libzypp-bindings build with gcc-4.7"
[platform/upstream/libzypp.git] / zypp / base / PtrTypes.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/base/PtrTypes.h
10  *  \ingroup ZYPP_SMART_PTR
11  *  \see ZYPP_SMART_PTR
12 */
13 #ifndef ZYPP_BASE_PTRTYPES_H
14 #define ZYPP_BASE_PTRTYPES_H
15
16 #include <string>
17
18 #include <boost/scoped_ptr.hpp>
19 #include <boost/shared_ptr.hpp>
20 #include <boost/weak_ptr.hpp>
21 #include <boost/intrusive_ptr.hpp>
22
23 ///////////////////////////////////////////////////////////////////
24 namespace zypp
25 { /////////////////////////////////////////////////////////////////
26
27     /** \defgroup ZYPP_SMART_PTR Smart pointer types
28      *  Smart pointer types.
29      *
30      * Namespace zypp provides 3 smart pointer types \b using the
31      * boost smart pointer library.
32      *
33      * \li \c scoped_ptr Simple sole ownership of single objects. Noncopyable.
34      *
35      * \li \c shared_ptr Object ownership shared among multiple pointers
36      *
37      * \li \c weak_ptr Non-owning observers of an object owned by shared_ptr.
38      *
39      * And \ref zypp::RW_pointer, as wrapper around a smart pointer,
40      * poviding \c const correct read/write access to the object it refers.
41     */
42     /*@{*/
43
44     /** shared_ptr custom deleter doing nothing.
45      * A custom deleter is a function being called when the
46      * last shared_ptr goes out of score. Per default the
47      * object gets deleted, but you can insall custom deleters
48      * as well. This one does nothing.
49      *
50      * \code
51      *  // Some class providing a std::istream
52      *  struct InpuStream
53      * {
54      *   // Per deafult use std::cin.
55      *   InputStream()
56      *   : _stream( &std::cin, NullDeleter() )
57      *   {}
58      *   // Or read from a file.
59      *   InputStream( const Pathname & file_r )
60      *   : _stream( new ifgzstream( _path.asString().c_str() ) )
61      *   {}
62      *   // Or use a stream priovided by the application.
63      *   InputStream( std::istream & stream_r )
64      *   : _stream( &stream_r, NullDeleter() )
65      *   {}
66      *
67      *   std::istream & stream()
68      *   { return *_stream; }
69      *
70      * private:
71      *   shared_ptr<std::istream> _stream;
72      * };
73      * \endcode
74     */
75     struct NullDeleter
76     {
77       void operator()( const void *const ) const
78       {}
79     };
80
81     /** \class scoped_ptr */
82     using boost::scoped_ptr;
83
84     /** \class shared_ptr */
85     using boost::shared_ptr;
86
87     /** \class weak_ptr */
88     using boost::weak_ptr;
89
90     /** \class intrusive_ptr */
91     using boost::intrusive_ptr;
92
93     /** */
94     using boost::static_pointer_cast;
95     /**  */
96     using boost::const_pointer_cast;
97     /**  */
98     using boost::dynamic_pointer_cast;
99
100   /////////////////////////////////////////////////////////////////
101 } // namespace zypp
102 ///////////////////////////////////////////////////////////////////
103 ///////////////////////////////////////////////////////////////////
104 namespace std
105 { /////////////////////////////////////////////////////////////////
106
107   // namespace sub {
108   //    class Foo;
109   //    typedef zypp::intrusive_ptr<Foo> Foo_Ptr; // see DEFINE_PTR_TYPE(NAME) macro below
110   // }
111
112   // Defined in namespace std g++ finds the output operator (König-Lookup),
113   // even if we typedef the pointer in a different namespace than ::zypp.
114   // Otherwise we had to define an output operator always in the same namespace
115   // as the typedef (else g++ will just print the pointer value).
116
117   /** \relates zypp::shared_ptr Stream output. */
118   template<class _D>
119   inline std::ostream & operator<<( std::ostream & str, const zypp::shared_ptr<_D> & obj )
120   {
121     if ( obj )
122       return str << *obj;
123     return str << std::string("NULL");
124   }
125   /** \relates zypp::shared_ptr Stream output. */
126   template<class _D>
127   inline std::ostream & dumpOn( std::ostream & str, const zypp::shared_ptr<_D> & obj )
128   {
129     if ( obj )
130       return dumpOn( str, *obj );
131     return str << std::string("NULL");
132   }
133
134   /** \relates zypp::intrusive_ptr Stream output. */
135   template<class _D>
136   inline std::ostream & operator<<( std::ostream & str, const zypp::intrusive_ptr<_D> & obj )
137   {
138     if ( obj )
139       return str << *obj;
140     return str << std::string("NULL");
141   }
142   /** \relates zypp::intrusive_ptr Stream output. */
143   template<class _D>
144   inline std::ostream & dumpOn( std::ostream & str, const zypp::intrusive_ptr<_D> & obj )
145   {
146     if ( obj )
147       return dumpOn( str, *obj );
148     return str << std::string("NULL");
149   }
150   /////////////////////////////////////////////////////////////////
151 } // namespace std
152 ///////////////////////////////////////////////////////////////////
153 ///////////////////////////////////////////////////////////////////
154 namespace zypp
155 { /////////////////////////////////////////////////////////////////
156
157     ///////////////////////////////////////////////////////////////////
158     //
159     //  RW_pointer traits
160     //
161     ///////////////////////////////////////////////////////////////////
162     /**
163      * Don't forgett to provide versions for _Ptr and _constPtr,
164      * esp. if creation a of temporary is not acceptable (eg. when
165      * checking the ref count value).
166     */
167     namespace rw_pointer {
168
169       template<class _D>
170         struct Shared
171         {
172           typedef shared_ptr<_D>       _Ptr;
173           typedef shared_ptr<const _D> _constPtr;
174           /** Check whether pointer is not shared. */
175           bool unique( const _constPtr & ptr_r )
176           { return !ptr_r || ptr_r.unique(); }
177           bool unique( const _Ptr & ptr_r )
178           { return !ptr_r || ptr_r.unique(); }
179           /** Return number of references. */
180           long use_count( const _constPtr & ptr_r ) const
181           { return ptr_r.use_count(); }
182           long use_count( const _Ptr & ptr_r ) const
183           { return ptr_r.use_count(); }
184         };
185
186       template<class _D>
187         struct Intrusive
188         {
189           typedef intrusive_ptr<_D>       _Ptr;
190           typedef intrusive_ptr<const _D> _constPtr;
191           /** Check whether pointer is not shared. */
192           bool unique( const _constPtr & ptr_r )
193           { return !ptr_r || (ptr_r->refCount() <= 1); }
194           bool unique( const _Ptr & ptr_r )
195           { return !ptr_r || (ptr_r->refCount() <= 1); }
196           /** Return number of references. */
197           long use_count( const _constPtr & ptr_r ) const
198           { return ptr_r ? ptr_r->refCount() : 0; }
199           long use_count( const _Ptr & ptr_r ) const
200           { return ptr_r ? ptr_r->refCount() : 0; }
201         };
202
203        template<class _D>
204         struct Scoped
205         {
206           typedef scoped_ptr<_D>       _Ptr;
207           typedef scoped_ptr<const _D> _constPtr;
208           /** Check whether pointer is not shared. */
209           bool unique( const _constPtr & ptr_r )
210           { return true; }
211           bool unique( const _Ptr & ptr_r )
212           { return true; }
213           /** Return number of references. */
214           long use_count( const _constPtr & ptr_r ) const
215           { return ptr_r ? 1 : 0; }
216           long use_count( const _Ptr & ptr_r ) const
217           { return ptr_r ? 1 : 0; }
218         };
219
220    }
221     ///////////////////////////////////////////////////////////////////
222
223     ///////////////////////////////////////////////////////////////////
224     //
225     //  CLASS NAME : RW_pointer
226     //
227     /** Wrapper for \c const correct access via \ref ZYPP_SMART_PTR.
228      *
229      * zypp::RW_pointer<tt>\<_D,_Traits></tt> stores a \ref ZYPP_SMART_PTR
230      * of type \c _Traits::_Ptr, which must be convertible into a <tt>_D *</tt>.
231      * Pointer style access (via \c -> and \c *) offers a <tt>const _D *</tt> in const
232      * a context, otherwise a <tt>_D *</tt>. Thus \em RW_ means \em read/write,
233      * as you get a different type, dependent on whether you're allowed to
234      * read or write.
235      *
236      * Forwarding access from an interface to an implemantation class, an
237      * RW_pointer prevents const interface methods from accidentally calling
238      * nonconst implementation methods.
239      *
240      * The second template argument defaults to
241      * <tt>_Traits = rw_pointer::Shared<_D></tt> thus wraping a
242      * <tt>shared_ptr<_D></tt>. To wrap an <tt>intrusive_ptr<_D></tt>
243      * use <tt>rw_pointer::Intrusive<_D></tt>.
244      *
245      * \see zypp::RWCOW_pointer for 'copy on write' functionality.
246      *
247      * \code
248      * #include "zypp/base/PtrTypes.h"
249      *
250      * class Foo
251      * {
252      *   ...
253      *   private:
254      *     // Implementation class
255      *     struct Impl;
256      *     // Pointer to implementation; actually a shared_ptr<Impl>
257      *     RW_pointer<Impl> _pimpl;
258      *
259      *     void baa()       { _pimpl->... } // is Impl *
260      *     void baa() const { _pimpl->... } // is Impl const *
261      * };
262      * \endcode
263     */
264     template<class _D, class _Traits = rw_pointer::Shared<_D> >
265       struct RW_pointer
266       {
267         typedef typename _Traits::_Ptr               _Ptr;
268         typedef typename _Traits::_constPtr          _constPtr;
269         typedef typename _Ptr::unspecified_bool_type unspecified_bool_type;
270
271         explicit
272         RW_pointer( typename _Ptr::element_type * dptr = 0 )
273         : _dptr( dptr )
274         {}
275
276         explicit
277         RW_pointer( _Ptr dptr )
278         : _dptr( dptr )
279         {}
280
281         void reset()
282         { _Ptr().swap( _dptr ); }
283
284         void reset( typename _Ptr::element_type * dptr )
285         { _Ptr( dptr ).swap( _dptr ); }
286
287         void swap( RW_pointer & rhs )
288         { _dptr.swap( rhs._dptr ); }
289
290         void swap( _Ptr & rhs )
291         { _dptr.swap( rhs ); }
292
293         operator unspecified_bool_type() const
294         { return _dptr; }
295
296         const _D & operator*() const
297         { return *_dptr; };
298
299         const _D * operator->() const
300         { return _dptr.get(); }
301
302         const _D * get() const
303         { return _dptr.get(); }
304
305         _D & operator*()
306         { return *_dptr; }
307
308         _D * operator->()
309         { return _dptr.get(); }
310
311         _D * get()
312         { return _dptr.get(); }
313
314       public:
315         bool unique() const
316         { return _Traits().unique( _dptr ); }
317
318         long use_count() const
319         { return _Traits().use_count( _dptr ); }
320
321         _constPtr getPtr() const
322         { return _dptr; }
323
324         _Ptr getPtr()
325         { return _dptr; }
326
327         _constPtr cgetPtr()
328         { return _dptr; }
329
330       private:
331         _Ptr _dptr;
332       };
333     ///////////////////////////////////////////////////////////////////
334
335     /** \relates RW_pointer Stream output.
336      *
337      * Print the \c _D object the RW_pointer refers, or \c "NULL"
338      * if the pointer is \c NULL.
339     */
340     template<class _D, class _Ptr>
341       inline std::ostream & operator<<( std::ostream & str, const RW_pointer<_D, _Ptr> & obj )
342       {
343         if ( obj.get() )
344           return str << *obj.get();
345         return str << std::string("NULL");
346       }
347
348     /** \relates RW_pointer */
349     template<class _D, class _Ptr>
350       inline bool operator==( const RW_pointer<_D, _Ptr> & lhs, const RW_pointer<_D, _Ptr> & rhs )
351       { return( lhs.get() == rhs.get() ); }
352     /** \relates RW_pointer */
353      template<class _D, class _Ptr>
354        inline bool operator==( const RW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_Ptr & rhs )
355        { return( lhs.get() == rhs.get() ); }
356     /** \relates RW_pointer */
357      template<class _D, class _Ptr>
358        inline bool operator==( const typename _Ptr::_Ptr & lhs, const RW_pointer<_D, _Ptr> & rhs )
359        { return( lhs.get() == rhs.get() ); }
360     /** \relates RW_pointer */
361      template<class _D, class _Ptr>
362        inline bool operator==( const RW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_constPtr & rhs )
363        { return( lhs.get() == rhs.get() ); }
364     /** \relates RW_pointer */
365      template<class _D, class _Ptr>
366        inline bool operator==( const typename _Ptr::_constPtr & lhs, const RW_pointer<_D, _Ptr> & rhs )
367        { return( lhs.get() == rhs.get() ); }
368
369
370     /** \relates RW_pointer */
371     template<class _D, class _Ptr>
372       inline bool operator!=( const RW_pointer<_D, _Ptr> & lhs, const RW_pointer<_D, _Ptr> & rhs )
373       { return ! ( lhs == rhs ); }
374     /** \relates RW_pointer */
375      template<class _D, class _Ptr>
376        inline bool operator!=( const RW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_Ptr & rhs )
377        { return ! ( lhs == rhs ); }
378     /** \relates RW_pointer */
379      template<class _D, class _Ptr>
380        inline bool operator!=( const typename _Ptr::_Ptr & lhs, const RW_pointer<_D, _Ptr> & rhs )
381        { return ! ( lhs == rhs ); }
382     /** \relates RW_pointer */
383      template<class _D, class _Ptr>
384        inline bool operator!=( const RW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_constPtr & rhs )
385        { return ! ( lhs == rhs ); }
386     /** \relates RW_pointer */
387      template<class _D, class _Ptr>
388        inline bool operator!=( const typename _Ptr::_constPtr & lhs, const RW_pointer<_D, _Ptr> & rhs )
389        { return ! ( lhs == rhs ); }
390
391     ///////////////////////////////////////////////////////////////////
392
393     ///////////////////////////////////////////////////////////////////
394     //
395     //  CLASS NAME : RWCOW_pointer
396     //
397     /** \ref RW_pointer supporting 'copy on write' functionality.
398      *
399      * \em Write access to the underlying object creates a copy, iff
400      * the object is shared.
401      *
402      * See \ref RW_pointer.
403     */
404     template<class _D, class _Traits = rw_pointer::Shared<_D> >
405       struct RWCOW_pointer
406       {
407         typedef typename _Traits::_Ptr               _Ptr;
408         typedef typename _Traits::_constPtr          _constPtr;
409         typedef typename _Ptr::unspecified_bool_type unspecified_bool_type;
410
411         explicit
412         RWCOW_pointer( typename _Ptr::element_type * dptr = 0 )
413         : _dptr( dptr )
414         {}
415
416         explicit
417         RWCOW_pointer( _Ptr dptr )
418         : _dptr( dptr )
419         {}
420
421         void reset()
422         { _Ptr().swap( _dptr ); }
423
424         void reset( typename _Ptr::element_type * dptr )
425         { _Ptr( dptr ).swap( _dptr ); }
426
427         void swap( RWCOW_pointer & rhs )
428         { _dptr.swap( rhs._dptr ); }
429
430         void swap( _Ptr & rhs )
431         { _dptr.swap( rhs ); }
432
433         operator unspecified_bool_type() const
434         { return _dptr; }
435
436         const _D & operator*() const
437         { return *_dptr; };
438
439         const _D * operator->() const
440         { return _dptr.get(); }
441
442         const _D * get() const
443         { return _dptr.get(); }
444
445         _D & operator*()
446         { assertUnshared(); return *_dptr; }
447
448         _D * operator->()
449         { assertUnshared(); return _dptr.get(); }
450
451         _D * get()
452         { assertUnshared(); return _dptr.get(); }
453
454       public:
455         bool unique() const
456         { return _Traits().unique( _dptr ); }
457
458         long use_count() const
459         { return _Traits().use_count( _dptr ); }
460
461         _constPtr getPtr() const
462         { return _dptr; }
463
464         _Ptr getPtr()
465         { assertUnshared(); return _dptr; }
466
467         _constPtr cgetPtr()
468         { return _dptr; }
469
470       private:
471
472         void assertUnshared()
473         {
474           if ( !unique() )
475             _Ptr( rwcowClone( _dptr.get() ) ).swap( _dptr );
476         }
477
478       private:
479         _Ptr _dptr;
480       };
481     ///////////////////////////////////////////////////////////////////
482
483     /** \relates RWCOW_pointer Clone the underlying object.
484      * Calls \a rhs <tt>-\>clone()</tt>. Being defined as a
485      * function outside \ref RWCOW_pointer allows to overload
486      * it, in case a specific \a _D does not have <tt>clone()</tt>.
487     */
488     template<class _D>
489       inline _D * rwcowClone( const _D * rhs )
490       { return rhs->clone(); }
491
492     ///////////////////////////////////////////////////////////////////
493
494     /** \relates RWCOW_pointer Stream output.
495      *
496      * Print the \c _D object the RWCOW_pointer refers, or \c "NULL"
497      * if the pointer is \c NULL.
498     */
499     template<class _D, class _Ptr>
500       inline std::ostream & operator<<( std::ostream & str, const RWCOW_pointer<_D, _Ptr> & obj )
501       {
502         if ( obj.get() )
503           return str << *obj.get();
504         return str << std::string("NULL");
505       }
506
507     /** \relates RWCOW_pointer */
508     template<class _D, class _Ptr>
509       inline bool operator==( const RWCOW_pointer<_D, _Ptr> & lhs, const RWCOW_pointer<_D, _Ptr> & rhs )
510       { return( lhs.get() == rhs.get() ); }
511     /** \relates RWCOW_pointer */
512     template<class _D, class _Ptr>
513       inline bool operator==( const RWCOW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_Ptr & rhs )
514       { return( lhs.get() == rhs.get() ); }
515     /** \relates RWCOW_pointer */
516     template<class _D, class _Ptr>
517       inline bool operator==( const typename _Ptr::_Ptr & lhs, const RWCOW_pointer<_D, _Ptr> & rhs )
518       { return( lhs.get() == rhs.get() ); }
519     /** \relates RWCOW_pointer */
520     template<class _D, class _Ptr>
521       inline bool operator==( const RWCOW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_constPtr & rhs )
522       { return( lhs.get() == rhs.get() ); }
523     /** \relates RWCOW_pointer */
524     template<class _D, class _Ptr>
525       inline bool operator==( const typename _Ptr::_constPtr & lhs, const RWCOW_pointer<_D, _Ptr> & rhs )
526       { return( lhs.get() == rhs.get() ); }
527
528     /** \relates RWCOW_pointer */
529     template<class _D, class _Ptr>
530       inline bool operator!=( const RWCOW_pointer<_D, _Ptr> & lhs, const RWCOW_pointer<_D, _Ptr> & rhs )
531       { return ! ( lhs == rhs ); }
532     /** \relates RWCOW_pointer */
533     template<class _D, class _Ptr>
534       inline bool operator!=( const RWCOW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_Ptr & rhs )
535       { return ! ( lhs == rhs ); }
536     /** \relates RWCOW_pointer */
537     template<class _D, class _Ptr>
538       inline bool operator!=( const typename _Ptr::_Ptr & lhs, const RWCOW_pointer<_D, _Ptr> & rhs )
539       { return ! ( lhs == rhs ); }
540     /** \relates RWCOW_pointer */
541     template<class _D, class _Ptr>
542       inline bool operator!=( const RWCOW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_constPtr & rhs )
543       { return ! ( lhs == rhs ); }
544     /** \relates RWCOW_pointer */
545     template<class _D, class _Ptr>
546       inline bool operator!=( const typename _Ptr::_constPtr & lhs, const RWCOW_pointer<_D, _Ptr> & rhs )
547       { return ! ( lhs == rhs ); }
548
549     ///////////////////////////////////////////////////////////////////
550
551     /*@}*/
552   /////////////////////////////////////////////////////////////////
553 } // namespace zypp
554 ///////////////////////////////////////////////////////////////////
555
556 /** Forward declaration of Ptr types */
557 #define DEFINE_PTR_TYPE(NAME) \
558 class NAME;                                                      \
559 extern void intrusive_ptr_add_ref( const NAME * );               \
560 extern void intrusive_ptr_release( const NAME * );               \
561 typedef zypp::intrusive_ptr<NAME>       NAME##_Ptr;        \
562 typedef zypp::intrusive_ptr<const NAME> NAME##_constPtr;
563
564 ///////////////////////////////////////////////////////////////////
565 #endif // ZYPP_BASE_PTRTYPES_H