@@ -59,6 +59,15 @@ constexpr auto calculate_size(size_t count) noexcept -> size_t {
5959 }
6060}
6161
62+ template <typename T>
63+ using void_pointer_for =
64+ std::conditional_t <std::is_const_v<T>, const void *, void *>;
65+
66+ template <typename To, typename From>
67+ constexpr auto pointer_cast (From* p) noexcept -> To* {
68+ return static_cast <To*>(static_cast <void_pointer_for<From>>(p));
69+ }
70+
6271} // namespace detail
6372
6473template <typename B, size_t Extent = dynamic_extent>
@@ -102,7 +111,7 @@ class byte_span {
102111 constexpr explicit (Extent != dynamic_extent
103112 || !detail::byte_like<std::iter_value_t <It>>)
104113 byte_span(It first, End last) noexcept (noexcept (last - first))
105- : span_{reinterpret_cast <pointer >(std::to_address (first)),
114+ : span_{detail::pointer_cast<element_type >(std::to_address (first)),
106115 detail::calculate_size<std::iter_value_t <It>>(
107116 static_cast <size_type>(last - first))} {}
108117
@@ -113,7 +122,7 @@ class byte_span {
113122 constexpr explicit (Extent != dynamic_extent
114123 || !detail::byte_like<std::iter_value_t <It>>)
115124 byte_span(It first, size_type count) noexcept
116- : span_{reinterpret_cast <pointer >(std::to_address (first)),
125+ : span_{detail::pointer_cast<element_type >(std::to_address (first)),
117126 detail::calculate_size<std::iter_value_t <It>>(count)} {}
118127
119128 // From void* - always explicit
@@ -122,7 +131,7 @@ class byte_span {
122131 requires std::is_void_v<VoidType>
123132 && detail::const_convertible<VoidType, element_type>
124133 constexpr explicit byte_span (VoidType* data, size_type size) noexcept
125- : span_{reinterpret_cast <pointer >(data), size} {}
134+ : span_{detail::pointer_cast<element_type >(data), size} {}
126135
127136 // From c-style arrays
128137 template <typename T, size_t ArrayExtent>
@@ -132,7 +141,7 @@ class byte_span {
132141 constexpr explicit (!detail::byte_like<T>)
133142 // NOLINTNEXTLINE
134143 byte_span(T (&arr)[ArrayExtent]) noexcept
135- : span_{reinterpret_cast <pointer>( arr),
144+ : span_{detail::pointer_cast<element_type>( std::data ( arr) ),
136145 detail::calculate_size<T>(ArrayExtent)} {}
137146
138147 // From std::array
@@ -143,7 +152,7 @@ class byte_span {
143152 constexpr explicit (!detail::byte_like<T>)
144153 // NOLINTNEXTLINE
145154 byte_span(std::array<T, ArrayExtent>& arr) noexcept
146- : span_{reinterpret_cast <pointer >(arr.data ()),
155+ : span_{detail::pointer_cast<element_type >(arr.data ()),
147156 detail::calculate_size<T>(ArrayExtent)} {}
148157
149158 // From const std::array
@@ -154,7 +163,7 @@ class byte_span {
154163 constexpr explicit (!detail::byte_like<T>)
155164 // NOLINTNEXTLINE
156165 byte_span(const std::array<T, ArrayExtent>& arr) noexcept
157- : span_{reinterpret_cast <pointer >(arr.data ()),
166+ : span_{detail::pointer_cast<element_type >(arr.data ()),
158167 detail::calculate_size<T>(ArrayExtent)} {}
159168
160169 // From Ranges
@@ -175,7 +184,7 @@ class byte_span {
175184 // NOLINTNEXTLINE
176185 byte_span(Range&& range) noexcept (noexcept (std::ranges::data(range))
177186 && noexcept (std::ranges::size(range)))
178- : span_{reinterpret_cast <pointer >(std::ranges::data (range)),
187+ : span_{detail::pointer_cast<element_type >(std::ranges::data (range)),
179188 detail::calculate_size<std::ranges::range_value_t <Range>>(
180189 std::ranges::size (range))} {
181190 if constexpr (Extent != dynamic_extent) {
@@ -196,7 +205,7 @@ class byte_span {
196205 || Extent != dynamic_extent)
197206 // NOLINTNEXTLINE
198207 byte_span(const std::span<OtherElementType, OtherExtent>& s) noexcept
199- : span_{reinterpret_cast <pointer >(s.data ()),
208+ : span_{detail::pointer_cast<element_type >(s.data ()),
200209 detail::calculate_size<OtherElementType>(s.size ())} {
201210 if constexpr (Extent != dynamic_extent) {
202211 assert (detail::calculate_size<OtherElementType>(s.size ()) == Extent);
@@ -349,15 +358,15 @@ constexpr void swap(byte_span<B, Extent>& lhs,
349358
350359template <typename B, size_t N>
351360constexpr auto as_sv (byte_span<B, N> bytes) noexcept -> std::string_view {
352- return {reinterpret_cast <const char * >(bytes.data ()), bytes.size ()};
361+ return {detail::pointer_cast <const char >(bytes.data ()), bytes.size ()};
353362}
354363
355364template <typename T, typename B, size_t N>
356365 requires std::is_trivially_copyable_v<T> && std::is_standard_layout_v<T>
357366 && (!std::is_void_v<T>) && (N == dynamic_extent || N >= sizeof (T))
358367constexpr auto as_value (byte_span<B, N> bytes) noexcept -> const T& {
359368 assert (bytes.size () >= sizeof (T));
360- return *std::launder (reinterpret_cast <const T* >(bytes.data ()));
369+ return *std::launder (detail::pointer_cast <const T>(bytes.data ()));
361370}
362371
363372// byte_span -> std::span<std::byte>
@@ -385,7 +394,7 @@ constexpr auto as_writable_span(byte_span<B, N> bytes) noexcept
385394 -> std::span<T, N == dynamic_extent ? dynamic_extent : N / sizeof(T)> {
386395 assert (bytes.size () % sizeof (T) == 0 );
387396 return std::span<T, (N == dynamic_extent ? dynamic_extent : N / sizeof (T))>{
388- std::launder (reinterpret_cast <T* >(bytes.data ())),
397+ std::launder (detail::pointer_cast<T >(bytes.data ())),
389398 bytes.size () / sizeof (T)};
390399}
391400
@@ -399,7 +408,7 @@ constexpr auto as_span(byte_span<B, N> bytes) noexcept
399408 assert (bytes.size () % sizeof (T) == 0 );
400409 return std::span<const T,
401410 (N == dynamic_extent ? dynamic_extent : N / sizeof (T))>{
402- std::launder (reinterpret_cast <const T* >(bytes.data ())),
411+ std::launder (detail::pointer_cast <const T>(bytes.data ())),
403412 bytes.size () / sizeof (T)};
404413}
405414
0 commit comments