Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:13:13

0001 #ifndef FWCore_Utilities_value_ptr_h
0002 #define FWCore_Utilities_value_ptr_h
0003 
0004 // ----------------------------------------------------------------------
0005 //
0006 // value_ptr.h - Smart pointer permitting copying of pointed-to object.
0007 //
0008 // Purpose: value_ptr provides a smart pointer template that provides
0009 // sole ownership of the pointed-to object. When a value_ptr object is
0010 // copied, the new value_ptr object is given a copy of the object pointed
0011 // to by the original value_ptr object.
0012 //
0013 // The value_ptr_traits template is provided to allow specialization
0014 // of the copying behavior. See the notes below.
0015 //
0016 // Use value_ptr only when deep-copying of the pointed-to object
0017 // is desireable. Use std::shared_ptr when sharing of the
0018 // pointed-to  object is desirable. Use std::unique_ptr
0019 // when no copying is desirable.
0020 //
0021 // The design of value_ptr is taken from Herb Sutter's More
0022 // Exceptional C++, with modifications by Marc Paterno and further
0023 // modifications by Walter Brown. This version is based on the
0024 // ValuePtr found in the Fermilab ZOOM library.
0025 //
0026 //
0027 // Supports the following syntax
0028 //   value_ptr<T> ptr(...);
0029 //   if (ptr) { ...
0030 // Where the conditional will evaluate as true if and only if the
0031 // pointer the value_ptr contains is not null.
0032 //
0033 // ----------------------------------------------------------------------
0034 
0035 #include <algorithm>  // for std::swap()
0036 #include <memory>
0037 #include "FWCore/Utilities/interface/get_underlying_safe.h"
0038 #include "FWCore/Utilities/interface/propagate_const.h"
0039 
0040 namespace edm {
0041 
0042   // --------------------------------------------------------------------
0043   //
0044   //  Auxiliary traits class template providing default clone()
0045   //  Users should specialize this template for types that have their
0046   //  own self-copy operations; failure to do so may lead to slicing!
0047   //
0048   // --------------------------------------------------------------------
0049 
0050   template <typename T>
0051   struct value_ptr_traits {
0052     static T* clone(T const* p) { return new T(*p); }
0053     static void destroy(T* p) { delete p; }
0054   };
0055 
0056   // --------------------------------------------------------------------
0057   //
0058   // Copyable smart pointer class template
0059   //
0060   // --------------------------------------------------------------------
0061 
0062   template <typename T>
0063   class value_ptr {
0064   public:
0065     // --------------------------------------------------
0066     // Default constructor/destructor:
0067     // --------------------------------------------------
0068 
0069     value_ptr() : myP(nullptr) {}
0070     explicit value_ptr(T* p) : myP(p) {}
0071     ~value_ptr() { value_ptr_traits<T>::destroy(myP.get()); }
0072 
0073     // --------------------------------------------------
0074     // Copy constructor/copy assignment:
0075     // --------------------------------------------------
0076 
0077     value_ptr(value_ptr const& orig) : myP(createFrom(get_underlying_safe(orig.myP))) {}
0078 
0079     value_ptr& operator=(value_ptr const& orig) {
0080       value_ptr<T> temp(orig);
0081       swap(temp);
0082       return *this;
0083     }
0084 
0085     // --------------------------------------------------
0086     // Move constructor/move assignment:
0087     // --------------------------------------------------
0088 
0089     value_ptr(value_ptr&& orig) : myP(orig.myP) { orig.myP = nullptr; }
0090 
0091     value_ptr& operator=(value_ptr&& orig) {
0092       if (myP != orig.myP) {
0093         delete myP.get();
0094         myP = orig.myP;
0095         orig.myP = nullptr;
0096       }
0097       return *this;
0098     }
0099 
0100     // --------------------------------------------------
0101     // Access mechanisms:
0102     // --------------------------------------------------
0103 
0104     T const& operator*() const { return *myP; }
0105     T& operator*() { return *myP; }
0106     T const* operator->() const { return get_underlying_safe(myP); }
0107     T* operator->() { return get_underlying_safe(myP); }
0108 
0109     // --------------------------------------------------
0110     // Manipulation:
0111     // --------------------------------------------------
0112 
0113     void swap(value_ptr& orig) { std::swap(myP, orig.myP); }
0114 
0115     // --------------------------------------------------
0116     // Copy-like construct/assign from compatible value_ptr<>:
0117     // --------------------------------------------------
0118 
0119     template <typename U>
0120     value_ptr(value_ptr<U> const& orig) : myP(createFrom(orig.operator->())) {}
0121 
0122     template <typename U>
0123     value_ptr& operator=(value_ptr<U> const& orig) {
0124       value_ptr<T> temp(orig);
0125       swap(temp);
0126       return *this;
0127     }
0128 
0129     // --------------------------------------------------
0130     // Move-like construct/assign from unique_ptr<>:
0131     // --------------------------------------------------
0132 
0133     value_ptr(std::unique_ptr<T> orig) : myP(orig.release()) { orig = nullptr; }
0134 
0135     value_ptr& operator=(std::unique_ptr<T> orig) {
0136       value_ptr<T> temp(std::move(orig));
0137       swap(temp);
0138       return *this;
0139     }
0140 
0141     // The following typedef, function, and operator definition
0142     // support the following syntax:
0143     //   value_ptr<T> ptr(..);
0144     //   if (ptr) { ...
0145     // Where the conditional will evaluate as true if and only if the
0146     // pointer value_ptr contains is not null.
0147   private:
0148     typedef void (value_ptr::*bool_type)() const;
0149     void this_type_does_not_support_comparisons() const {}
0150 
0151   public:
0152     operator bool_type() const {
0153       return myP != nullptr ? &value_ptr<T>::this_type_does_not_support_comparisons : nullptr;
0154     }
0155 
0156   private:
0157     // --------------------------------------------------
0158     // Implementation aid:
0159     // --------------------------------------------------
0160 
0161     template <typename U>
0162     static T* createFrom(U const* p) {
0163       return p ? value_ptr_traits<U>::clone(p) : nullptr;
0164     }
0165 
0166     // --------------------------------------------------
0167     // Member data:
0168     // --------------------------------------------------
0169 
0170     edm::propagate_const<T*> myP;
0171 
0172   };  // value_ptr
0173 
0174   // --------------------------------------------------------------------
0175   //
0176   // Free-standing swap()
0177   //
0178   // --------------------------------------------------------------------
0179 
0180   template <typename T>
0181   inline void swap(value_ptr<T>& vp1, value_ptr<T>& vp2) {
0182     vp1.swap(vp2);
0183   }
0184 
0185   // Do not allow nonsensical comparisons that the bool_type
0186   // conversion operator definition above would otherwise allow.
0187   // The function call inside the next 4 operator definitions is
0188   // private, so compilation will fail if there is an attempt to
0189   // instantiate these 4 operators.
0190   template <typename T, typename U>
0191   inline bool operator==(value_ptr<T> const& lhs, U const& rhs) {
0192     lhs.this_type_does_not_support_comparisons();
0193     return false;
0194   }
0195 
0196   template <typename T, typename U>
0197   inline bool operator!=(value_ptr<T> const& lhs, U const& rhs) {
0198     lhs.this_type_does_not_support_comparisons();
0199     return false;
0200   }
0201 
0202   template <typename T, typename U>
0203   inline bool operator==(U const& lhs, value_ptr<T> const& rhs) {
0204     rhs.this_type_does_not_support_comparisons();
0205     return false;
0206   }
0207 
0208   template <typename T, typename U>
0209   inline bool operator!=(U const& lhs, value_ptr<T> const& rhs) {
0210     rhs.this_type_does_not_support_comparisons();
0211     return false;
0212   }
0213 }  // namespace edm
0214 
0215 #endif  // FWCoreUtilities_value_ptr_h