CMS 3D CMS Logo

propagate_const_array.h
Go to the documentation of this file.
1 #ifndef FWCore_Utilities_interface_propagate_const_array_h
2 #define FWCore_Utilities_interface_propagate_const_array_h
3 // -*- C++ -*-
4 //
5 // Package: FWCore/Utilities
6 // Class : propagate_const_array
7 // Description: Propagate const to array-like objects. Based on C++ experimental std::propagate_const.
8 // If used with an array of incomplete type, edm::propagate_const_array can only be declared
9 // and assigned to nullptr, but not assigned to an actual object or dereferenced.
10 
11 // system include files
12 #include <cstddef>
13 #include <type_traits>
14 #include <utility>
15 
16 // user include files
17 
18 // forward declarations
19 
20 namespace edm {
21 
22  namespace impl {
23 
24  // check if a type T has a subscript operator T[N]
25  template <typename, typename = void>
26  struct has_subscript_operator : std::false_type {};
27 
28  template <typename T>
29  struct has_subscript_operator<T, std::void_t<decltype(std::declval<T&>()[0])>> : std::true_type {};
30 
31  template <typename T>
33 
34  // for a type T, return the type of the return value of the subscript operator T[N]
35  template <typename T, typename = void, typename = void>
36  struct subscript_type {};
37 
38  // the specialisations for arrays allow supporting incomplete types
39  template <typename T>
40  struct subscript_type<T[]> {
41  using type = T;
42  };
43 
44  template <typename T, int N>
45  struct subscript_type<T[N]> {
46  using type = T;
47  };
48 
49  // for non-array types that implement the subscript operator[], a complete type is needed
50  template <typename T>
51  struct subscript_type<T, std::enable_if_t<not std::is_array_v<T>>, std::enable_if_t<has_subscript_operator_v<T>>> {
52  using type = typename std::remove_reference<decltype(std::declval<T&>()[0])>::type;
53  };
54 
55  template <typename T>
57 
58  } // namespace impl
59 
60  template <typename T>
62 
63  template <typename T>
64  constexpr std::decay_t<T>& get_underlying(propagate_const_array<T>&);
65  template <typename T>
66  constexpr std::decay_t<T> const& get_underlying(propagate_const_array<T> const&);
67 
68  template <typename T>
69  class propagate_const_array {
70  public:
71  friend constexpr std::decay_t<T>& get_underlying<T>(propagate_const_array<T>&);
72  friend constexpr std::decay_t<T> const& get_underlying<T>(propagate_const_array<T> const&);
73 
74  template <typename U>
75  friend class propagate_const_array;
76 
78 
79  constexpr propagate_const_array() = default;
80  constexpr propagate_const_array(propagate_const_array<T>&&) = default;
82  template <typename U>
83  constexpr propagate_const_array(U&& u) : m_value(std::forward<U>(u)) {}
84 
87 
88  template <typename U>
90  static_assert(std::is_convertible_v<std::decay_t<U>, std::decay_t<T>>,
91  "Cannot assign propagate_const_array<> of incompatible types");
92  m_value = other.m_value;
93  return *this;
94  }
95 
96  template <typename U>
97  constexpr propagate_const_array& operator=(U&& u) {
98  m_value = std::forward<U>(u);
99  return *this;
100  }
101 
102  // ---------- const member functions ---------------------
103  constexpr element_type const* get() const { return &m_value[0]; }
104  constexpr element_type const& operator[](std::ptrdiff_t pos) const { return m_value[pos]; }
105 
106  constexpr operator element_type const*() const { return this->get(); }
107 
108  // ---------- member functions ---------------------------
109  constexpr element_type* get() { return &m_value[0]; }
110  constexpr element_type& operator[](std::ptrdiff_t pos) { return m_value[pos]; }
111 
112  constexpr operator element_type*() { return this->get(); }
113 
114  private:
115  // ---------- member data --------------------------------
116  std::decay_t<T> m_value;
117  };
118 
119  template <typename T>
120  constexpr std::decay_t<T>& get_underlying(propagate_const_array<T>& iP) {
121  return iP.m_value;
122  }
123 
124  template <typename T>
125  constexpr std::decay_t<T> const& get_underlying(propagate_const_array<T> const& iP) {
126  return iP.m_value;
127  }
128 
129 } // namespace edm
130 
131 #endif // FWCore_Utilities_interface_propagate_const_array_h
constexpr element_type & operator[](std::ptrdiff_t pos)
typename subscript_type< T >::type subscript_type_t
constexpr propagate_const_array()=default
constexpr propagate_const_array< T > & operator=(propagate_const_array &&)=default
#define N
Definition: blowfish.cc:9
constexpr propagate_const_array & operator=(U &&u)
constexpr T & get_underlying(propagate_const< T > &)
constexpr auto has_subscript_operator_v
HLT enums.
constexpr propagate_const_array & operator=(propagate_const_array< U > &other)
long double T
typename impl::subscript_type_t< cms::cuda::device::unique_ptr< double[]> > element_type
constexpr propagate_const_array(U &&u)
constexpr element_type const & operator[](std::ptrdiff_t pos) const