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.

4394. simd::unchecked_load(I first, S last) construct span maybe ill-formed

Section: 29.10.8.7 [simd.loadstore] Status: New Submitter: Hewill Kang Opened: 2025-09-30 Last modified: 2025-10-03

Priority: Not Prioritized

View other active issues in [simd.loadstore].

View all other issues in [simd.loadstore].

View all issues with New status.

Discussion:

Currently, simd::unchecked_load/partial_load/unchecked_store/partial_store constructs a span via span(first, last) when taking an iterator-sentinel pair first and last.

However, the construction may not be well-behaved or well-formed when the sentinel type can be implicitly converted to an integer type. Consider:

struct I {
  using value_type = int;
  using difference_type = int;
  using iterator_category = std::contiguous_iterator_tag;
  // contiguous iterator operators
  // ...
 
  operator int() const;
};

int main() {
   std::simd::unchecked_load(I{}, I{});
}

Above, unchecked_load invokes unchecked_load(I first, S last) and we attempt to construct span through span(first, last). However, this is invalid because the constructor requires that the sentinel type should not be convertible to size_t, so we fall back into span(first, n) via implicitly converting I to size_t. Such behavior is subtle and likely unintended.

Now consider:

struct I {
  using value_type = int;
  using difference_type = int;
  using iterator_category = std::contiguous_iterator_tag;
  // contiguous iterator operators
  // ...

  operator int() &&;
};

int main() {
   std::simd::unchecked_load(I{}, I{});
}

We still attempt to construct the span by calling span(first, last), which is invalid, but because the lvalue sentinel cannot be converted to size_t, the call of span(first, n) is also invalid. This makes the construction of the span ill-formed and leads to a hard error in the function body.

Proposed resolution:

This wording is relative to N5014.

  1. In subclause 29.10.8.7 [simd.loadstore] replace all occurrences of

    R(first, last)
    

    by

    R(first, static_cast<size_t>(last - first))