Imported Upstream version 16.3.2
[platform/upstream/libzypp.git] / zypp / base / PtrTypes.h
index ba6c195..d0a6cf4 100644 (file)
@@ -13,6 +13,7 @@
 #ifndef ZYPP_BASE_PTRTYPES_H
 #define ZYPP_BASE_PTRTYPES_H
 
+#include <iosfwd>
 #include <string>
 
 #include <boost/scoped_ptr.hpp>
 namespace zypp
 { /////////////////////////////////////////////////////////////////
 
+  namespace str
+  {
+    // printing void* (prevents us from including <ostream>)
+    std::string form( const char * format, ... ) __attribute__ ((format (printf, 1, 2)));
+  }
+
     /** \defgroup ZYPP_SMART_PTR Smart pointer types
      *  Smart pointer types.
      *
@@ -41,7 +48,44 @@ namespace zypp
     */
     /*@{*/
 
-    /** \class scoped_ptr scoped_ptr */
+    /** shared_ptr custom deleter doing nothing.
+     * A custom deleter is a function being called when the
+     * last shared_ptr goes out of score. Per default the
+     * object gets deleted, but you can insall custom deleters
+     * as well. This one does nothing.
+     *
+     * \code
+     *  // Some class providing a std::istream
+     *  struct InpuStream
+     * {
+     *   // Per deafult use std::cin.
+     *   InputStream()
+     *   : _stream( &std::cin, NullDeleter() )
+     *   {}
+     *   // Or read from a file.
+     *   InputStream( const Pathname & file_r )
+     *   : _stream( new ifgzstream( _path.asString().c_str() ) )
+     *   {}
+     *   // Or use a stream priovided by the application.
+     *   InputStream( std::istream & stream_r )
+     *   : _stream( &stream_r, NullDeleter() )
+     *   {}
+     *
+     *   std::istream & stream()
+     *   { return *_stream; }
+     *
+     * private:
+     *   shared_ptr<std::istream> _stream;
+     * };
+     * \endcode
+    */
+    struct NullDeleter
+    {
+      void operator()( const void *const ) const
+      {}
+    };
+
+    /** \class scoped_ptr */
     using boost::scoped_ptr;
 
     /** \class shared_ptr */
@@ -53,40 +97,147 @@ namespace zypp
     /** \class intrusive_ptr */
     using boost::intrusive_ptr;
 
-    /**  */
+    /** */
     using boost::static_pointer_cast;
     /**  */
     using boost::const_pointer_cast;
     /**  */
     using boost::dynamic_pointer_cast;
 
+  /////////////////////////////////////////////////////////////////
+} // namespace zypp
+///////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////
+namespace std
+{ /////////////////////////////////////////////////////////////////
+
+  // namespace sub {
+  //    class Foo;
+  //    typedef zypp::intrusive_ptr<Foo> Foo_Ptr; // see DEFINE_PTR_TYPE(NAME) macro below
+  // }
+
+  // Defined in namespace std g++ finds the output operator (König-Lookup),
+  // even if we typedef the pointer in a different namespace than ::zypp.
+  // Otherwise we had to define an output operator always in the same namespace
+  // as the typedef (else g++ will just print the pointer value).
+
+  /** \relates zypp::shared_ptr Stream output. */
+  template<class D>
+  inline std::ostream & operator<<( std::ostream & str, const zypp::shared_ptr<D> & obj )
+  {
+    if ( obj )
+      return str << *obj;
+    return str << std::string("NULL");
+  }
+  /** \overload specialize for void */
+  template<>
+  inline std::ostream & operator<<( std::ostream & str, const zypp::shared_ptr<void> & obj )
+  {
+    if ( obj )
+      return str << zypp::str::form( "%p", (void*)obj.get() );
+    return str << std::string("NULL");
+  }
+
+  /** \relates zypp::shared_ptr Stream output. */
+  template<class D>
+  inline std::ostream & dumpOn( std::ostream & str, const zypp::shared_ptr<D> & obj )
+  {
+    if ( obj )
+      return dumpOn( str, *obj );
+    return str << std::string("NULL");
+  }
+  /** \overload specialize for void */
+  template<>
+  inline std::ostream & dumpOn( std::ostream & str, const zypp::shared_ptr<void> & obj )
+  { return str << obj; }
+
+  /** \relates zypp::intrusive_ptr Stream output. */
+  template<class D>
+  inline std::ostream & operator<<( std::ostream & str, const zypp::intrusive_ptr<D> & obj )
+  {
+    if ( obj )
+      return str << *obj;
+    return str << std::string("NULL");
+  }
+  /** \relates zypp::intrusive_ptr Stream output. */
+  template<class D>
+  inline std::ostream & dumpOn( std::ostream & str, const zypp::intrusive_ptr<D> & obj )
+  {
+    if ( obj )
+      return dumpOn( str, *obj );
+    return str << std::string("NULL");
+  }
+  /////////////////////////////////////////////////////////////////
+} // namespace std
+///////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////
+namespace zypp
+{ /////////////////////////////////////////////////////////////////
+
     ///////////////////////////////////////////////////////////////////
     //
     // RW_pointer traits
     //
     ///////////////////////////////////////////////////////////////////
+    /**
+     * Don't forgett to provide versions for PtrType and constPtrType,
+     * esp. if creation a of temporary is not acceptable (eg. when
+     * checking the ref count value).
+    */
     namespace rw_pointer {
 
-      template<class _D>
+      template<class D>
         struct Shared
         {
-          typedef shared_ptr<_D>       _Ptr;
-          typedef shared_ptr<const _D> _constPtr;
-          /** Check whether pointer is shared. */
-          bool isShared( const _constPtr & ptr_r )
-          { return ptr_r.use_count() > 1; }
+          typedef shared_ptr<D>       PtrType;
+          typedef shared_ptr<const D> constPtrType;
+          /** Check whether pointer is not shared. */
+          bool unique( const constPtrType & ptr_r )
+          { return !ptr_r || ptr_r.unique(); }
+          bool unique( const PtrType & ptr_r )
+          { return !ptr_r || ptr_r.unique(); }
+          /** Return number of references. */
+          long use_count( const constPtrType & ptr_r ) const
+          { return ptr_r.use_count(); }
+          long use_count( const PtrType & ptr_r ) const
+          { return ptr_r.use_count(); }
         };
 
-      template<class _D>
+      template<class D>
         struct Intrusive
         {
-          typedef intrusive_ptr<_D>       _Ptr;
-          typedef intrusive_ptr<const _D> _constPtr;
-          /** Check whether pointer is shared. */
-          bool isShared( const _constPtr & ptr_r )
-          { return ptr_r && (ptr_r->refCount() > 1); }
+          typedef intrusive_ptr<D>       PtrType;
+          typedef intrusive_ptr<const D> constPtrType;
+          /** Check whether pointer is not shared. */
+          bool unique( const constPtrType & ptr_r )
+          { return !ptr_r || (ptr_r->refCount() <= 1); }
+          bool unique( const PtrType & ptr_r )
+          { return !ptr_r || (ptr_r->refCount() <= 1); }
+          /** Return number of references. */
+          long use_count( const constPtrType & ptr_r ) const
+          { return ptr_r ? ptr_r->refCount() : 0; }
+          long use_count( const PtrType & ptr_r ) const
+          { return ptr_r ? ptr_r->refCount() : 0; }
+        };
+
+       template<class D>
+        struct Scoped
+        {
+          typedef scoped_ptr<D>       PtrType;
+          typedef scoped_ptr<const D> constPtrType;
+          /** Check whether pointer is not shared. */
+          bool unique( const constPtrType & ptr_r )
+          { return true; }
+          bool unique( const PtrType & ptr_r )
+          { return true; }
+          /** Return number of references. */
+          long use_count( const constPtrType & ptr_r ) const
+          { return ptr_r ? 1 : 0; }
+          long use_count( const PtrType & ptr_r ) const
+          { return ptr_r ? 1 : 0; }
         };
-    }
+
+   }
     ///////////////////////////////////////////////////////////////////
 
     ///////////////////////////////////////////////////////////////////
@@ -95,10 +246,10 @@ namespace zypp
     //
     /** Wrapper for \c const correct access via \ref ZYPP_SMART_PTR.
      *
-     * zypp::RW_pointer<tt>\<_D,_Traits></tt> stores a \ref ZYPP_SMART_PTR
-     * of type \c _Traits::_Ptr, which must be convertible into a <tt>_D *</tt>.
-     * Pointer style access (via \c -> and \c *) offers a <tt>const _D *</tt> in const
-     * a context, otherwise a <tt>_D *</tt>. Thus \em RW_ means \em read/write,
+     * zypp::RW_pointer<tt>\<D,DTraits></tt> stores a \ref ZYPP_SMART_PTR
+     * of type \c DTraits::PtrType, which must be convertible into a <tt>D *</tt>.
+     * Pointer style access (via \c -> and \c *) offers a <tt>const D *</tt> in const
+     * a context, otherwise a <tt>D *</tt>. Thus \em RW_ means \em read/write,
      * as you get a different type, dependent on whether you're allowed to
      * read or write.
      *
@@ -107,9 +258,9 @@ namespace zypp
      * nonconst implementation methods.
      *
      * The second template argument defaults to
-     * <tt>_Traits = rw_pointer::Shared<_D></tt> thus wraping a
-     * <tt>shared_ptr<_D></tt>. To wrap an <tt>intrusive_ptr<_D></tt>
-     * use <tt>rw_pointer::Intrusive<_D></tt>.
+     * <tt>DTraits = rw_pointer::Shared<D></tt> thus wraping a
+     * <tt>shared_ptr<D></tt>. To wrap an <tt>intrusive_ptr<D></tt>
+     * use <tt>rw_pointer::Intrusive<D></tt>.
      *
      * \see zypp::RWCOW_pointer for 'copy on write' functionality.
      *
@@ -130,90 +281,168 @@ namespace zypp
      * };
      * \endcode
     */
-    template<class _D, class _Traits = rw_pointer::Shared<_D> >
+    template<class D, class DTraits = rw_pointer::Shared<D> >
       struct RW_pointer
       {
-        typedef typename _Traits::_Ptr               _Ptr;
-        typedef typename _Traits::_constPtr          _constPtr;
-        typedef typename _Ptr::unspecified_bool_type unspecified_bool_type;
+        typedef typename DTraits::PtrType               PtrType;
+        typedef typename DTraits::constPtrType          constPtrType;
+
+        RW_pointer()
+        {}
+
+        RW_pointer( std::nullptr_t )
+        {}
 
         explicit
-        RW_pointer( typename _Ptr::element_type * dptr = 0 )
+        RW_pointer( typename PtrType::element_type * dptr )
         : _dptr( dptr )
         {}
 
         explicit
-        RW_pointer( _Ptr dptr )
+        RW_pointer( PtrType dptr )
         : _dptr( dptr )
         {}
 
+        RW_pointer & operator=( std::nullptr_t )
+       { reset(); return *this; }
+
         void reset()
-        { _dptr.reset(); }
+        { PtrType().swap( _dptr ); }
 
-        void reset( typename _Ptr::element_type * dptr )
-        { _dptr.reset( dptr ); }
+        void reset( typename PtrType::element_type * dptr )
+        { PtrType( dptr ).swap( _dptr ); }
 
         void swap( RW_pointer & rhs )
         { _dptr.swap( rhs._dptr ); }
 
-        void swap( _Ptr & rhs )
+        void swap( PtrType & rhs )
         { _dptr.swap( rhs ); }
 
-        operator unspecified_bool_type() const
-        { return _dptr; }
+        explicit operator bool() const
+        { return _dptr.get() != nullptr; }
 
-        const _D & operator*() const
+        const D & operator*() const
         { return *_dptr; };
 
-        const _D * operator->() const
-        { return _dptr.get(); }
+        const D * operator->() const
+        { return _dptr.operator->(); }
 
-        const _D * get() const
+        const D * get() const
         { return _dptr.get(); }
 
-        _D & operator*()
+        D & operator*()
         { return *_dptr; }
 
-        _D * operator->()
-        { return _dptr.get(); }
+        D * operator->()
+        { return _dptr.operator->(); }
 
-        _D * get()
+        D * get()
         { return _dptr.get(); }
 
       public:
-        bool      unique() const
-       { return _dptr.unique(); }
+        bool unique() const
+       { return DTraits().unique( _dptr ); }
 
-       long      use_count() const
-       { return _dptr.use_count(); }
+       long use_count() const
+       { return DTraits().use_count( _dptr ); }
+
+        constPtrType getPtr() const
+        { return _dptr; }
 
-        _constPtr getPtr() const
+        PtrType getPtr()
         { return _dptr; }
 
-        _Ptr getPtr()
+        constPtrType cgetPtr()
         { return _dptr; }
 
       private:
-        _Ptr _dptr;
+        PtrType _dptr;
       };
     ///////////////////////////////////////////////////////////////////
 
     /** \relates RW_pointer Stream output.
      *
-     * Print the \c _D object the RW_pointer refers, or \c "NULL"
+     * Print the \c D object the RW_pointer refers, or \c "NULL"
      * if the pointer is \c NULL.
-    */
-    template<class _D, class _Ptr>
-      inline std::ostream &
-      operator<<( std::ostream & str, const RW_pointer<_D, _Ptr> & obj )
+     */
+    template<class D, class DPtr>
+      inline std::ostream & operator<<( std::ostream & str, const RW_pointer<D, DPtr> & obj )
       {
         if ( obj.get() )
           return str << *obj.get();
         return str << std::string("NULL");
       }
 
+    /** \relates RW_pointer */
+    template<class D, class DPtr>
+      inline bool operator==( const RW_pointer<D, DPtr> & lhs, const RW_pointer<D, DPtr> & rhs )
+      { return( lhs.get() == rhs.get() ); }
+    /** \relates RW_pointer */
+    template<class D, class DPtr>
+      inline bool operator==( const RW_pointer<D, DPtr> & lhs, const typename DPtr::PtrType & rhs )
+      { return( lhs.get() == rhs.get() ); }
+    /** \relates RW_pointer */
+    template<class D, class DPtr>
+      inline bool operator==( const typename DPtr::PtrType & lhs, const RW_pointer<D, DPtr> & rhs )
+      { return( lhs.get() == rhs.get() ); }
+    /** \relates RW_pointer */
+    template<class D, class DPtr>
+      inline bool operator==( const RW_pointer<D, DPtr> & lhs, const typename DPtr::constPtrType & rhs )
+      { return( lhs.get() == rhs.get() ); }
+    /** \relates RW_pointer */
+    template<class D, class DPtr>
+      inline bool operator==( const typename DPtr::constPtrType & lhs, const RW_pointer<D, DPtr> & rhs )
+      { return( lhs.get() == rhs.get() ); }
+    /** \relates RW_pointer */
+    template<class D, class DPtr>
+      inline bool operator==( const RW_pointer<D, DPtr> & lhs, std::nullptr_t )
+      { return( lhs.get() == nullptr ); }
+    /** \relates RW_pointer */
+    template<class D, class DPtr>
+      inline bool operator==( std::nullptr_t, const RW_pointer<D, DPtr> & rhs )
+      { return( nullptr == rhs.get() ); }
+
+
+    /** \relates RW_pointer */
+    template<class D, class DPtr>
+      inline bool operator!=( const RW_pointer<D, DPtr> & lhs, const RW_pointer<D, DPtr> & rhs )
+      { return ! ( lhs == rhs ); }
+    /** \relates RW_pointer */
+    template<class D, class DPtr>
+      inline bool operator!=( const RW_pointer<D, DPtr> & lhs, const typename DPtr::PtrType & rhs )
+      { return ! ( lhs == rhs ); }
+    /** \relates RW_pointer */
+    template<class D, class DPtr>
+      inline bool operator!=( const typename DPtr::PtrType & lhs, const RW_pointer<D, DPtr> & rhs )
+      { return ! ( lhs == rhs ); }
+    /** \relates RW_pointer */
+    template<class D, class DPtr>
+      inline bool operator!=( const RW_pointer<D, DPtr> & lhs, const typename DPtr::constPtrType & rhs )
+      { return ! ( lhs == rhs ); }
+    /** \relates RW_pointer */
+    template<class D, class DPtr>
+      inline bool operator!=( const typename DPtr::constPtrType & lhs, const RW_pointer<D, DPtr> & rhs )
+      { return ! ( lhs == rhs ); }
+    /** \relates RW_pointer */
+    template<class D, class DPtr>
+      inline bool operator!=( const RW_pointer<D, DPtr> & lhs, std::nullptr_t )
+      { return( lhs.get() != nullptr ); }
+    /** \relates RW_pointer */
+    template<class D, class DPtr>
+      inline bool operator!=( std::nullptr_t, const RW_pointer<D, DPtr> & rhs )
+      { return( nullptr != rhs.get() ); }
+
     ///////////////////////////////////////////////////////////////////
 
+    /** \relates RWCOW_pointer Clone the underlying object.
+     * Calls \a rhs <tt>-\>clone()</tt>. Being defined as a
+     * function outside \ref RWCOW_pointer allows to overload
+     * it, in case a specific \a D does not have <tt>clone()</tt>.
+     */
+    template<class D>
+      inline D * rwcowClone( const D * rhs )
+      { return rhs->clone(); }
+
     ///////////////////////////////////////////////////////////////////
     //
     // CLASS NAME : RWCOW_pointer
@@ -225,107 +454,167 @@ namespace zypp
      *
      * See \ref RW_pointer.
     */
-    template<class _D, class _Traits = rw_pointer::Shared<_D> >
+    template<class D, class DTraits = rw_pointer::Shared<D> >
       struct RWCOW_pointer
       {
-        typedef typename _Traits::_Ptr               _Ptr;
-        typedef typename _Traits::_constPtr          _constPtr;
-        typedef typename _Ptr::unspecified_bool_type unspecified_bool_type;
+        typedef typename DTraits::PtrType               PtrType;
+        typedef typename DTraits::constPtrType          constPtrType;
+
+       RWCOW_pointer()
+       {}
+
+       RWCOW_pointer( std::nullptr_t )
+       {}
 
         explicit
-        RWCOW_pointer( typename _Ptr::element_type * dptr = 0 )
+        RWCOW_pointer( typename PtrType::element_type * dptr )
         : _dptr( dptr )
         {}
 
         explicit
-        RWCOW_pointer( _Ptr dptr )
+        RWCOW_pointer( PtrType dptr )
         : _dptr( dptr )
         {}
 
+        RWCOW_pointer & operator=( std::nullptr_t )
+       { reset(); return *this; }
+
         void reset()
-        { _dptr.reset(); }
+        { PtrType().swap( _dptr ); }
 
-        void reset( typename _Ptr::element_type * dptr )
-        { _dptr.reset( dptr ); }
+        void reset( typename PtrType::element_type * dptr )
+        { PtrType( dptr ).swap( _dptr ); }
 
         void swap( RWCOW_pointer & rhs )
         { _dptr.swap( rhs._dptr ); }
 
-        void swap( _Ptr & rhs )
+        void swap( PtrType & rhs )
         { _dptr.swap( rhs ); }
 
-        operator unspecified_bool_type() const
-        { return _dptr; }
+        explicit operator bool() const
+       { return _dptr.get() != nullptr; }
 
-        const _D & operator*() const
+        const D & operator*() const
         { return *_dptr; };
 
-        const _D * operator->() const
-        { return _dptr.get(); }
+        const D * operator->() const
+        { return _dptr.operator->(); }
 
-        const _D * get() const
+        const D * get() const
         { return _dptr.get(); }
 
-        _D & operator*()
+        D & operator*()
         { assertUnshared(); return *_dptr; }
 
-        _D * operator->()
-        { assertUnshared(); return _dptr.get(); }
+        D * operator->()
+        { assertUnshared(); return _dptr.operator->(); }
 
-        _D * get()
+        D * get()
         { assertUnshared(); return _dptr.get(); }
 
       public:
-        _constPtr getPtr() const
+        bool unique() const
+       { return DTraits().unique( _dptr ); }
+
+       long use_count() const
+       { return DTraits().use_count( _dptr ); }
+
+        constPtrType getPtr() const
         { return _dptr; }
 
-        _Ptr getPtr()
+        PtrType getPtr()
         { assertUnshared(); return _dptr; }
 
+        constPtrType cgetPtr()
+        { return _dptr; }
+
       private:
 
         void assertUnshared()
         {
-          if ( _Traits().isShared( _dptr ) )
-            {
-              _dptr.reset( rwcowClone( _dptr.get() ) );
-            }
+          if ( !unique() )
+            PtrType( rwcowClone( _dptr.get() ) ).swap( _dptr );
         }
 
       private:
-        _Ptr _dptr;
+        PtrType _dptr;
       };
     ///////////////////////////////////////////////////////////////////
 
-    /** \relates RWCOW_pointer Clone the underlying object.
-     * Calls \a rhs <tt>-\>clone()</tt>. Being defined as a
-     * function outside \ref RWCOW_pointer allows to overload
-     * it, in case a specific \a _D does not have <tt>clone()</tt>.
-    */
-    template<class _D>
-      inline _D * rwcowClone( const _D * rhs )
-      { return rhs->clone(); }
-
-    ///////////////////////////////////////////////////////////////////
-
     /** \relates RWCOW_pointer Stream output.
      *
-     * Print the \c _D object the RWCOW_pointer refers, or \c "NULL"
+     * Print the \c D object the RWCOW_pointer refers, or \c "NULL"
      * if the pointer is \c NULL.
-    */
-    template<class _D, class _Ptr>
-      inline std::ostream &
-      operator<<( std::ostream & str, const RWCOW_pointer<_D, _Ptr> & obj )
+     */
+    template<class D, class DPtr>
+      inline std::ostream & operator<<( std::ostream & str, const RWCOW_pointer<D, DPtr> & obj )
       {
         if ( obj.get() )
           return str << *obj.get();
         return str << std::string("NULL");
       }
 
+    /** \relates RWCOW_pointer */
+    template<class D, class DPtr>
+      inline bool operator==( const RWCOW_pointer<D, DPtr> & lhs, const RWCOW_pointer<D, DPtr> & rhs )
+      { return( lhs.get() == rhs.get() ); }
+    /** \relates RWCOW_pointer */
+    template<class D, class DPtr>
+      inline bool operator==( const RWCOW_pointer<D, DPtr> & lhs, const typename DPtr::PtrType & rhs )
+      { return( lhs.get() == rhs.get() ); }
+    /** \relates RWCOW_pointer */
+    template<class D, class DPtr>
+      inline bool operator==( const typename DPtr::PtrType & lhs, const RWCOW_pointer<D, DPtr> & rhs )
+      { return( lhs.get() == rhs.get() ); }
+    /** \relates RWCOW_pointer */
+    template<class D, class DPtr>
+      inline bool operator==( const RWCOW_pointer<D, DPtr> & lhs, const typename DPtr::constPtrType & rhs )
+      { return( lhs.get() == rhs.get() ); }
+    /** \relates RWCOW_pointer */
+    template<class D, class DPtr>
+      inline bool operator==( const typename DPtr::constPtrType & lhs, const RWCOW_pointer<D, DPtr> & rhs )
+      { return( lhs.get() == rhs.get() ); }
+    /** \relates RWCOW_pointer */
+    template<class D, class DPtr>
+      inline bool operator==( const RWCOW_pointer<D, DPtr> & lhs, std::nullptr_t )
+      { return( lhs.get() == nullptr ); }
+    /** \relates RWCOW_pointer */
+    template<class D, class DPtr>
+      inline bool operator==( std::nullptr_t, const RWCOW_pointer<D, DPtr> & rhs )
+      { return( nullptr == rhs.get() ); }
+
+    /** \relates RWCOW_pointer */
+    template<class D, class DPtr>
+      inline bool operator!=( const RWCOW_pointer<D, DPtr> & lhs, const RWCOW_pointer<D, DPtr> & rhs )
+      { return ! ( lhs == rhs ); }
+    /** \relates RWCOW_pointer */
+    template<class D, class DPtr>
+      inline bool operator!=( const RWCOW_pointer<D, DPtr> & lhs, const typename DPtr::PtrType & rhs )
+      { return ! ( lhs == rhs ); }
+    /** \relates RWCOW_pointer */
+    template<class D, class DPtr>
+      inline bool operator!=( const typename DPtr::PtrType & lhs, const RWCOW_pointer<D, DPtr> & rhs )
+      { return ! ( lhs == rhs ); }
+    /** \relates RWCOW_pointer */
+    template<class D, class DPtr>
+      inline bool operator!=( const RWCOW_pointer<D, DPtr> & lhs, const typename DPtr::constPtrType & rhs )
+      { return ! ( lhs == rhs ); }
+    /** \relates RWCOW_pointer */
+    template<class D, class DPtr>
+      inline bool operator!=( const typename DPtr::constPtrType & lhs, const RWCOW_pointer<D, DPtr> & rhs )
+      { return ! ( lhs == rhs ); }
+    /** \relates RWCOW_pointer */
+    template<class D, class DPtr>
+      inline bool operator!=( const RWCOW_pointer<D, DPtr> & lhs, std::nullptr_t )
+      { return( lhs.get() != nullptr ); }
+    /** \relates RWCOW_pointer */
+    template<class D, class DPtr>
+      inline bool operator!=( std::nullptr_t, const RWCOW_pointer<D, DPtr> & rhs )
+      { return( nullptr != rhs.get() ); }
+
     ///////////////////////////////////////////////////////////////////
 
     /*@}*/
-
   /////////////////////////////////////////////////////////////////
 } // namespace zypp
 ///////////////////////////////////////////////////////////////////