File indexing completed on 2024-08-25 23:07:07
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 namespace impl {
0022
0023 template <typename T>
0024 concept ArrayAddressable = requires(T& a) { a[0]; } or std::is_array_v<T>;
0025
0026
0027 template <typename T, typename = void, typename = void>
0028 struct subscript_type {};
0029
0030
0031 template <typename T>
0032 struct subscript_type<T[]> {
0033 using type = T;
0034 };
0035
0036 template <typename T, int N>
0037 struct subscript_type<T[N]> {
0038 using type = T;
0039 };
0040
0041
0042 template <typename T>
0043 requires requires {
0044 requires not std::is_array_v<T>;
0045 requires ArrayAddressable<T>;
0046 }
0047 struct subscript_type<T> {
0048 using type = typename std::remove_reference<decltype(std::declval<T&>()[0])>::type;
0049 };
0050
0051 template <typename T>
0052 using subscript_type_t = typename subscript_type<T>::type;
0053
0054 }
0055
0056 template <impl::ArrayAddressable T>
0057 class propagate_const_array;
0058
0059 template <typename T>
0060 constexpr std::decay_t<T>& get_underlying(propagate_const_array<T>&);
0061 template <typename T>
0062 constexpr std::decay_t<T> const& get_underlying(propagate_const_array<T> const&);
0063
0064 template <impl::ArrayAddressable T>
0065 class propagate_const_array {
0066 public:
0067 friend constexpr std::decay_t<T>& get_underlying<T>(propagate_const_array<T>&);
0068 friend constexpr std::decay_t<T> const& get_underlying<T>(propagate_const_array<T> const&);
0069
0070 template <impl::ArrayAddressable U>
0071 friend class propagate_const_array;
0072
0073 using element_type = typename impl::subscript_type_t<T>;
0074
0075 constexpr propagate_const_array() = default;
0076 constexpr propagate_const_array(propagate_const_array<T>&&) = default;
0077 propagate_const_array(propagate_const_array<T> const&) = delete;
0078 template <typename U>
0079 constexpr propagate_const_array(U&& u) : m_value(std::forward<U>(u)) {}
0080
0081 constexpr propagate_const_array<T>& operator=(propagate_const_array&&) = default;
0082 propagate_const_array<T>& operator=(propagate_const_array<T> const&) = delete;
0083
0084 template <typename U>
0085 constexpr propagate_const_array& operator=(propagate_const_array<U>& other) {
0086 static_assert(std::is_convertible_v<std::decay_t<U>, std::decay_t<T>>,
0087 "Cannot assign propagate_const_array<> of incompatible types");
0088 m_value = other.m_value;
0089 return *this;
0090 }
0091
0092 template <typename U>
0093 constexpr propagate_const_array& operator=(U&& u) {
0094 m_value = std::forward<U>(u);
0095 return *this;
0096 }
0097
0098
0099 constexpr element_type const* get() const { return &m_value[0]; }
0100 constexpr element_type const& operator[](std::ptrdiff_t pos) const { return m_value[pos]; }
0101
0102 constexpr operator element_type const*() const { return this->get(); }
0103
0104
0105 constexpr element_type* get() { return &m_value[0]; }
0106 constexpr element_type& operator[](std::ptrdiff_t pos) { return m_value[pos]; }
0107
0108 constexpr operator element_type*() { return this->get(); }
0109
0110 private:
0111
0112 std::decay_t<T> m_value;
0113 };
0114
0115 template <typename T>
0116 constexpr std::decay_t<T>& get_underlying(propagate_const_array<T>& iP) {
0117 return iP.m_value;
0118 }
0119
0120 template <typename T>
0121 constexpr std::decay_t<T> const& get_underlying(propagate_const_array<T> const& iP) {
0122 return iP.m_value;
0123 }
0124
0125 }
0126
0127 #endif