Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 #ifndef FWCore_Utilities_propagate_const_h
0002 #define FWCore_Utilities_propagate_const_h
0003 // -*- C++ -*-
0004 //
0005 // Package:     FWCore/Utilities
0006 // Class  :     propagate_const
0007 //
0008 /**\class propagate_const propagate_const.h "FWCore/Utilities/interface/propagate_const.h"
0009 
0010  Description: propagate const to pointer like objects. Based on C++ experimental std::propagate_const.
0011 
0012  Usage:
0013     <usage>
0014 
0015 */
0016 //
0017 // Original Author:  Chris Jones
0018 //         Created:  Fri, 18 Dec 2015 14:56:12 GMT
0019 //
0020 
0021 // system include files
0022 #include <type_traits>
0023 #include <utility>
0024 
0025 // user include files
0026 
0027 // forward declarations
0028 
0029 namespace edm {
0030 
0031   template <typename T>
0032   class propagate_const;
0033 
0034   template <typename T>
0035   constexpr T& get_underlying(propagate_const<T>&);
0036   template <typename T>
0037   constexpr T const& get_underlying(propagate_const<T> const&);
0038 
0039   template <typename T>
0040   class propagate_const {
0041   public:
0042     friend constexpr T& get_underlying<T>(propagate_const<T>&);
0043     friend constexpr T const& get_underlying<T>(propagate_const<T> const&);
0044 
0045     using element_type = typename std::remove_reference<decltype(*std::declval<T&>())>::type;
0046 
0047     constexpr propagate_const() = default;
0048 
0049     constexpr propagate_const(propagate_const<T>&&) = default;
0050     propagate_const(propagate_const<T> const&) = delete;
0051     template <typename U>
0052     constexpr propagate_const(U&& iValue) : m_value(std::forward<U>(iValue)) {}
0053 
0054     constexpr propagate_const<T>& operator=(propagate_const&&) = default;
0055     propagate_const<T>& operator=(propagate_const<T> const&) = delete;
0056 
0057     template <typename U>
0058     constexpr propagate_const& operator=(U&& iValue) {
0059       m_value = std::forward<U>(iValue);
0060       return *this;
0061     }
0062 
0063     // ---------- const member functions ---------------------
0064     constexpr element_type const* get() const { return to_raw_pointer(m_value); }
0065     constexpr element_type const* operator->() const { return this->get(); }
0066     constexpr element_type const& operator*() const { return *m_value; }
0067 
0068     constexpr operator element_type const*() const { return this->get(); }
0069 
0070     // ---------- member functions ---------------------------
0071     constexpr element_type* get() { return to_raw_pointer(m_value); }
0072     constexpr element_type* operator->() { return this->get(); }
0073     constexpr element_type& operator*() { return *m_value; }
0074 
0075     constexpr operator element_type*() { return this->get(); }
0076 
0077   private:
0078     template <typename Up>
0079     static constexpr element_type* to_raw_pointer(Up* u) {
0080       return u;
0081     }
0082 
0083     template <typename Up>
0084     static constexpr element_type* to_raw_pointer(Up& u) {
0085       return u.get();
0086     }
0087 
0088     template <typename Up>
0089     static constexpr const element_type* to_raw_pointer(const Up* u) {
0090       return u;
0091     }
0092 
0093     template <typename Up>
0094     static constexpr const element_type* to_raw_pointer(const Up& u) {
0095       return u.get();
0096     }
0097 
0098     // ---------- member data --------------------------------
0099     T m_value;
0100   };
0101 
0102   template <typename T>
0103   constexpr T& get_underlying(propagate_const<T>& iP) {
0104     return iP.m_value;
0105   }
0106   template <typename T>
0107   constexpr T const& get_underlying(propagate_const<T> const& iP) {
0108     return iP.m_value;
0109   }
0110 
0111 }  // namespace edm
0112 
0113 #endif