Title
`as_bytes`/`as_writable_bytes` is broken with span<volatile T>
Status
new
Section
[span.objectrep]
Submitter
Hewill Kang

Created on 2025-04-12.00:00:00 last changed 2 weeks ago

Messages

Date: 2025-04-21.09:42:41

Proposed resolution:

This wording is relative to N5008.

  1. Modify [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> is `false`.

    -1- Effects: Equivalent to: return R{reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
    where R is 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> is `false` and is_volatile_v<ElementType> is `false`.

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

Date: 2025-04-15.00:00:00

[ 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`.

Date: 2025-04-21.09:42:41

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
}

This wording is relative to N5008.

  1. Modify [span.syn], header <span> synopsis, as indicated:

    […]
    namespace std {
      […]
      // [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 [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.

History
Date User Action Args
2025-04-21 09:42:41adminsetmessages: + msg14724
2025-04-13 10:11:07adminsetmessages: + msg14723
2025-04-12 00:00:00admincreate