File indexing completed on 2023-04-28 04:48:21
0001 #ifndef FWCore_Utilities_interface_propagate_const_array_h
0002 #define FWCore_Utilities_interface_propagate_const_array_h
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <cstddef>
0013 #include <type_traits>
0014 #include <utility>
0015
0016
0017
0018
0019
0020 namespace edm {
0021
0022 namespace impl {
0023
0024
0025 template <typename, typename = void>
0026 struct has_subscript_operator : std::false_type {};
0027
0028 template <typename T>
0029 struct has_subscript_operator<T, std::void_t<decltype(std::declval<T&>()[0])>> : std::true_type {};
0030
0031 template <typename T>
0032 constexpr auto has_subscript_operator_v = has_subscript_operator<T>::value;
0033
0034
0035 template <typename T, typename = void, typename = void>
0036 struct subscript_type {};
0037
0038
0039 template <typename T>
0040 struct subscript_type<T[]> {
0041 using type = T;
0042 };
0043
0044 template <typename T, int N>
0045 struct subscript_type<T[N]> {
0046 using type = T;
0047 };
0048
0049
0050 template <typename T>
0051 struct subscript_type<T, std::enable_if_t<not std::is_array_v<T>>, std::enable_if_t<has_subscript_operator_v<T>>> {
0052 using type = typename std::remove_reference<decltype(std::declval<T&>()[0])>::type;
0053 };
0054
0055 template <typename T>
0056 using subscript_type_t = typename subscript_type<T>::type;
0057
0058 }
0059
0060 template <typename T>
0061 class propagate_const_array;
0062
0063 template <typename T>
0064 constexpr std::decay_t<T>& get_underlying(propagate_const_array<T>&);
0065 template <typename T>
0066 constexpr std::decay_t<T> const& get_underlying(propagate_const_array<T> const&);
0067
0068 template <typename T>
0069 class propagate_const_array {
0070 public:
0071 friend constexpr std::decay_t<T>& get_underlying<T>(propagate_const_array<T>&);
0072 friend constexpr std::decay_t<T> const& get_underlying<T>(propagate_const_array<T> const&);
0073
0074 template <typename U>
0075 friend class propagate_const_array;
0076
0077 using element_type = typename impl::subscript_type_t<T>;
0078
0079 constexpr propagate_const_array() = default;
0080 constexpr propagate_const_array(propagate_const_array<T>&&) = default;
0081 propagate_const_array(propagate_const_array<T> const&) = delete;
0082 template <typename U>
0083 constexpr propagate_const_array(U&& u) : m_value(std::forward<U>(u)) {}
0084
0085 constexpr propagate_const_array<T>& operator=(propagate_const_array&&) = default;
0086 propagate_const_array<T>& operator=(propagate_const_array<T> const&) = delete;
0087
0088 template <typename U>
0089 constexpr propagate_const_array& operator=(propagate_const_array<U>& other) {
0090 static_assert(std::is_convertible_v<std::decay_t<U>, std::decay_t<T>>,
0091 "Cannot assign propagate_const_array<> of incompatible types");
0092 m_value = other.m_value;
0093 return *this;
0094 }
0095
0096 template <typename U>
0097 constexpr propagate_const_array& operator=(U&& u) {
0098 m_value = std::forward<U>(u);
0099 return *this;
0100 }
0101
0102
0103 constexpr element_type const* get() const { return &m_value[0]; }
0104 constexpr element_type const& operator[](std::ptrdiff_t pos) const { return m_value[pos]; }
0105
0106 constexpr operator element_type const*() const { return this->get(); }
0107
0108
0109 constexpr element_type* get() { return &m_value[0]; }
0110 constexpr element_type& operator[](std::ptrdiff_t pos) { return m_value[pos]; }
0111
0112 constexpr operator element_type*() { return this->get(); }
0113
0114 private:
0115
0116 std::decay_t<T> m_value;
0117 };
0118
0119 template <typename T>
0120 constexpr std::decay_t<T>& get_underlying(propagate_const_array<T>& iP) {
0121 return iP.m_value;
0122 }
0123
0124 template <typename T>
0125 constexpr std::decay_t<T> const& get_underlying(propagate_const_array<T> const& iP) {
0126 return iP.m_value;
0127 }
0128
0129 }
0130
0131 #endif