This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.

4243. as_bytes/as_writable_bytes is broken with span<volatile T>

Section: 23.7.2.3 [span.objectrep] Status: New Submitter: Hewill Kang Opened: 2025-04-12 Last modified: 2025-04-13

Priority: Not Prioritized

View all issues with New 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
}

Proposed resolution:

This wording is relative to N5008.

  1. 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;
    }
    
  2. 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()};
    where R is 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> is false.

    -3- Effects: Equivalent to: return R{reinterpret_cast<R::pointerbyte*>(s.data()), s.size_bytes()};
    where R is the return type.