as_bytes/as_writable_bytes is broken with span<volatile T>Section: 23.7.2.3 [span.objectrep] Status: Ready Submitter: Hewill Kang Opened: 2025-04-12 Last modified: 2025-06-17
Priority: 4
View all issues with Ready status.
Discussion:
They both use reinterpret_cast to cast the underlying pointer type of span to const byte*
and byte* respectively, which leads to a hard error when the element type is volatile-qualified
(demo):
#include <span>
int main() {
std::span<volatile int> span;
auto bytes = as_bytes(span); // hard error
auto writable_bytes = as_writable_bytes(span); // hard error
}
Previous resolution [SUPERSEDED]:
This wording is relative to N5008.
Modify 23.7.2.1 [span.syn], header
<span>synopsis, as indicated:[…] namespace std { […] // 23.7.2.3 [span.objectrep], views of object representation template<class ElementType, size_t Extent> span<const conditional_t<is_volatile_v<ElementType>, volatile byte, byte>, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent> as_bytes(span<ElementType, Extent> s) noexcept; template<class ElementType, size_t Extent> span<conditional_t<is_volatile_v<ElementType>, volatile byte, byte>, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent> as_writable_bytes(span<ElementType, Extent> s) noexcept; }Modify 23.7.2.3 [span.objectrep] as indicated:
template<class ElementType, size_t Extent> span<const conditional_t<is_volatile_v<ElementType>, volatile byte, byte>, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent> as_bytes(span<ElementType, Extent> s) noexcept;-1- Effects: Equivalent to:
return R{reinterpret_cast<R::pointerconst byte*>(s.data()), s.size_bytes()};
whereRis the return type.template<class ElementType, size_t Extent> span<conditional_t<is_volatile_v<ElementType>, volatile byte, byte>, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent> as_writable_bytes(span<ElementType, Extent> s) noexcept;-2- Constraints:
is_const_v<ElementType>isfalse.-3- Effects: Equivalent to:
return R{reinterpret_cast<R::pointerbyte*>(s.data()), s.size_bytes()};
whereRis the return type.
[2025-04-16; Hewill Kang provides alternative wording]
Based on reflector feedback, the revised wording just improves the current state of not supporting
support for volatile.
[2025-06-12; Reflector poll]
Set priority to 4 after reflector poll.
[Sofia 2025-06-17; Move to Ready]
Proposed resolution:
This wording is relative to N5008.
Modify 23.7.2.3 [span.objectrep] as indicated:
template<class ElementType, size_t Extent> span<const byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent> as_bytes(span<ElementType, Extent> s) noexcept;-?- Constraints:
is_volatile_v<ElementType>isfalse.-1- Effects: Equivalent to:
return R{reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
whereRis the return type.template<class ElementType, size_t Extent> span<byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent> as_writable_bytes(span<ElementType, Extent> s) noexcept;-2- Constraints:
is_const_v<ElementType>isfalseandis_volatile_v<ElementType>isfalse.-3- Effects: Equivalent to:
return R{reinterpret_cast<byte*>(s.data()), s.size_bytes()};
whereRis the return type.