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.

4393. simd::unchecked_scatter_to is underconstrained

Section: 29.10.8.11 [simd.permute.memory] Status: New Submitter: Hewill Kang Opened: 2025-09-29 Last modified: 2025-10-03

Priority: Not Prioritized

View all issues with New status.

Discussion:

Both simd::unchecked_scatter_to and simd::partial_scatter_to are used to write a simd::vec into a range R.

However, they only require R to be contiguous_range and sized_range. Requiring R to be output_range is also necessary; otherwise, the constant_range cannot be written.

Proposed resolution:

This wording is relative to N5014.

  1. Modify 29.10.3 [simd.syn] as indicated:

    namespace std::simd {
      […]
      template<simd-vec-type V, ranges::contiguous_range R, simd-integral I, class... Flags>
        requires ranges::sized_range<R> && ranges::output_range<R, typename V::value_type>
        constexpr void
          unchecked_scatter_to(const V& v, R&& out,
                               const I& indices, flags<Flags...> f = {});
      template<simd-vec-type V, ranges::contiguous_range R, simd-integral I, class... Flags>
        requires ranges::sized_range<R> && ranges::output_range<R, typename V::value_type>
        constexpr void
          unchecked_scatter_to(const V& v, R&& out, const typename I::mask_type& mask,
                               const I& indices, flags<Flags...> f = {});
    
      template<simd-vec-type V, ranges::contiguous_range R, simd-integral I, class... Flags>
        requires ranges::sized_range<R> && ranges::output_range<R, typename V::value_type>
        constexpr void
          partial_scatter_to(const V& v, R&& out,
                             const I& indices, flags<Flags...> f = {});
      template<simd-vec-type V, ranges::contiguous_range R, simd-integral I, class... Flags>
        requires ranges::sized_range<R> && ranges::output_range<R, typename V::value_type>
        constexpr void
          partial_scatter_to(const V& v, R&& out, const typename I::mask_type& mask,
                             const I& indices, flags<Flags...> f = {});
      […]
    }
    
  2. Modify 29.10.8.11 [simd.permute.memory] as indicated:

    template<simd-vec-type V, ranges::contiguous_range R, simd-integral I, class... Flags>
      requires ranges::sized_range<R> && ranges::output_range<R, typename V::value_type>
      constexpr void unchecked_scatter_to(const V& v, R&& out, const I& indices,
                                          flags<Flags...> f = {});
    template<simd-vec-type V, ranges::contiguous_range R, simd-integral I, class... Flags>
      requires ranges::sized_range<R> && ranges::output_range<R, typename V::value_type>
      constexpr void unchecked_scatter_to(const V& v, R&& out, const typename I::mask_type& mask,
                                          const I& indices, flags<Flags...> f = {});
    

    -10- Let mask be typename I::mask_type(true) for the overload with no mask parameter.

    […]

    template<simd-vec-type V, ranges::contiguous_range R, simd-integral I, class... Flags>
      requires ranges::sized_range<R> && ranges::output_range<R, typename V::value_type>
      constexpr void
      partial_scatter_to(const V& v, R&& out, const I& indices, flags<Flags...> f = {});
    template<simd-vec-type V, ranges::contiguous_range R, simd-integral I, class... Flags>
      requires ranges::sized_range<R> && ranges::output_range<R, typename V::value_type>
      constexpr void partial_scatter_to(const V& v, R&& out, const typename I::mask_type& mask,
                                        const I& indices, flags<Flags...> f = {});
    

    -13- Let mask be typename I::mask_type(true) for the overload with no mask parameter.

    […]