Files
project_6/cccl_upstream/libcudacxx/include/cuda/std/span
EngineX CI 56fd68e7dd [INFRA] Import NVIDIA/CCCL upstream as optimization reference library
CCCL (CUDA C++ Core Libraries) provides:
- CUB: device/block/warp-level GPU primitives (reduce, scan, sort, topk)
- Thrust: high-level parallel algorithms (transform_reduce, sort, scan)
- libcudacxx: CUDA C++ standard library (atomics, barriers, memory)
- cudax: experimental features (memory resources, allocators)
- Tuning policies: per-SM hardware-specific algorithm parameters

Competition optimization vectors mapped to CCCL:
- Output TPS (83% weight): warp_reduce, block_reduce, device_topk
- Input TPS (14% weight): device_scan, block_load, prefetch
- Cache TPS (3% weight): prefix caching strategy patterns
- Memory (0.9 util): pooled/cached/buddy allocators

Source: https://github.com/NVIDIA/cccl (shallow clone, HEAD only)
License: Apache-2.0
2026-07-30 09:35:51 +00:00

654 lines
24 KiB
Plaintext

//===----------------------------------------------------------------------===//
//
// Part of libcu++, the C++ Standard Library for your entire system,
// under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES.
//
//===----------------------------------------------------------------------===//
#ifndef _CUDA_STD_SPAN
#define _CUDA_STD_SPAN
#include <cuda/std/detail/__config>
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
# pragma GCC system_header
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
# pragma clang system_header
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
# pragma system_header
#endif // no system header
#include <cuda/std/__concepts/concept_macros.h>
#include <cuda/std/__concepts/convertible_to.h>
#include <cuda/std/__concepts/equality_comparable.h>
#include <cuda/std/__exception/exception_macros.h>
#include <cuda/std/__fwd/array.h>
#include <cuda/std/__fwd/span.h>
#include <cuda/std/__fwd/string.h>
#include <cuda/std/__host_stdlib/stdexcept>
#include <cuda/std/__iterator/access.h>
#include <cuda/std/__iterator/concepts.h>
#include <cuda/std/__iterator/data.h>
#include <cuda/std/__iterator/distance.h>
#include <cuda/std/__iterator/empty.h>
#include <cuda/std/__iterator/reverse_access.h>
#include <cuda/std/__iterator/reverse_iterator.h>
#include <cuda/std/__iterator/size.h>
#include <cuda/std/__iterator/wrap_iter.h>
#include <cuda/std/__ranges/concepts.h>
#include <cuda/std/__ranges/data.h>
#include <cuda/std/__ranges/enable_borrowed_range.h>
#include <cuda/std/__ranges/enable_view.h>
#include <cuda/std/__ranges/size.h>
#include <cuda/std/__type_traits/integral_constant.h>
#include <cuda/std/__type_traits/integral_constant_like.h>
#include <cuda/std/__type_traits/is_array.h>
#include <cuda/std/__type_traits/is_const.h>
#include <cuda/std/__type_traits/is_convertible.h>
#include <cuda/std/__type_traits/is_integral.h>
#include <cuda/std/__type_traits/is_same.h>
#include <cuda/std/__type_traits/remove_const.h>
#include <cuda/std/__type_traits/remove_cv.h>
#include <cuda/std/__type_traits/remove_cvref.h>
#include <cuda/std/__type_traits/remove_reference.h>
#include <cuda/std/__type_traits/type_identity.h>
#include <cuda/std/array>
#include <cuda/std/cstddef>
#include <cuda/std/initializer_list>
#include <cuda/std/version>
#include <cuda/std/__cccl/prologue.h>
_CCCL_BEGIN_NAMESPACE_CUDA_STD
template <class _From, class _To>
_CCCL_CONCEPT __span_array_convertible = is_convertible_v<_From (*)[], _To (*)[]>;
template <class _Range, class _ElementType>
_CCCL_CONCEPT __span_compatible_range = _CCCL_REQUIRES_EXPR((_Range, _ElementType))(
requires(::cuda::std::ranges::contiguous_range<_Range>),
requires(::cuda::std::ranges::sized_range<_Range>),
requires((::cuda::std::ranges::borrowed_range<_Range> || is_const_v<_ElementType>) ),
requires((!is_array_v<remove_cvref_t<_Range>>) ),
requires((!__is_cuda_std_span_v<remove_cvref_t<_Range>> && !__is_cuda_std_array_v<remove_cvref_t<_Range>>) ),
requires(
is_convertible_v<remove_reference_t<::cuda::std::ranges::range_reference_t<_Range>> (*)[], _ElementType (*)[]>));
template <class _It, class _Tp>
_CCCL_CONCEPT __span_compatible_iterator = _CCCL_REQUIRES_EXPR((_It, _Tp)) //
(requires(contiguous_iterator<_It>),
requires(__span_array_convertible<remove_reference_t<iter_reference_t<_It>>, _Tp>));
template <class _Sentinel, class _It>
_CCCL_CONCEPT __span_compatible_sentinel_for = _CCCL_REQUIRES_EXPR((_Sentinel, _It)) //
(requires(sized_sentinel_for<_Sentinel, _It>), requires(!is_convertible_v<_Sentinel, size_t>));
template <class _Tp, bool = __integral_constant_like<_Tp>>
inline constexpr size_t __maybe_static_ext = dynamic_extent;
template <class _Tp>
inline constexpr size_t __maybe_static_ext<_Tp, true> = {_Tp::value};
template <typename _Tp, size_t _Extent>
class _CCCL_TYPE_VISIBILITY_DEFAULT span
{
public:
// constants and types
using element_type = _Tp;
using value_type = remove_cv_t<_Tp>;
using size_type = size_t;
using difference_type = ptrdiff_t;
using pointer = _Tp*;
using const_pointer = const _Tp*;
using reference = _Tp&;
using const_reference = const _Tp&;
using iterator = __wrap_iter<pointer>;
using reverse_iterator = ::cuda::std::reverse_iterator<iterator>;
static constexpr size_type extent = _Extent;
// [span.cons], span constructors, copy, assignment, and destructor
_CCCL_TEMPLATE(size_t _Sz = _Extent)
_CCCL_REQUIRES((_Sz == 0))
_CCCL_API constexpr span() noexcept
: __data_{nullptr}
{}
_CCCL_HIDE_FROM_ABI span(const span&) noexcept = default;
_CCCL_HIDE_FROM_ABI span& operator=(const span&) noexcept = default;
_CCCL_EXEC_CHECK_DISABLE
_CCCL_TEMPLATE(class _It)
_CCCL_REQUIRES(__span_compatible_iterator<_It, element_type>)
_CCCL_API constexpr explicit span(_It __first, [[maybe_unused]] size_type __count)
: __data_{::cuda::std::to_address(__first)}
{
_CCCL_ASSERT(_Extent == __count, "size mismatch in span's constructor (iterator, len)");
}
_CCCL_EXEC_CHECK_DISABLE
_CCCL_TEMPLATE(class _It, class _End)
_CCCL_REQUIRES(__span_compatible_iterator<_It, element_type> _CCCL_AND __span_compatible_sentinel_for<_End, _It>)
_CCCL_API constexpr explicit span(_It __first, [[maybe_unused]] _End __last)
: __data_{::cuda::std::to_address(__first)}
{
_CCCL_ASSERT((__last - __first >= 0), "invalid range in span's constructor (iterator, sentinel)");
_CCCL_ASSERT(__last - __first == _Extent,
"invalid range in span's constructor (iterator, sentinel): last - first != extent");
}
_CCCL_TEMPLATE(size_t _Sz = _Extent)
_CCCL_REQUIRES((_Sz != 0))
_CCCL_API constexpr span(type_identity_t<element_type> (&__arr)[_Sz]) noexcept
: __data_{__arr}
{}
_CCCL_TEMPLATE(class _OtherElementType)
_CCCL_REQUIRES(__span_array_convertible<_OtherElementType, element_type>)
_CCCL_API constexpr span(array<_OtherElementType, _Extent>& __arr) noexcept
: __data_{__arr.data()}
{}
_CCCL_TEMPLATE(class _OtherElementType)
_CCCL_REQUIRES(__span_array_convertible<const _OtherElementType, element_type>)
_CCCL_API constexpr span(const array<_OtherElementType, _Extent>& __arr) noexcept
: __data_{__arr.data()}
{}
#if _CCCL_HAS_HOST_STD_LIB()
_CCCL_EXEC_CHECK_DISABLE
_CCCL_TEMPLATE(class _OtherElementType)
_CCCL_REQUIRES(__span_array_convertible<_OtherElementType, element_type>)
_CCCL_HOST_API constexpr span(::std::array<_OtherElementType, _Extent>& __arr) noexcept
: __data_{__arr.data()}
{}
_CCCL_EXEC_CHECK_DISABLE
_CCCL_TEMPLATE(class _OtherElementType)
_CCCL_REQUIRES(__span_array_convertible<const _OtherElementType, element_type>)
_CCCL_HOST_API constexpr span(const ::std::array<_OtherElementType, _Extent>& __arr) noexcept
: __data_{__arr.data()}
{}
#endif // _CCCL_HAS_HOST_STD_LIB()
// NOLINTBEGIN(bugprone-forwarding-reference-overload)
_CCCL_EXEC_CHECK_DISABLE
_CCCL_TEMPLATE(class _Range)
_CCCL_REQUIRES(__span_compatible_range<_Range, element_type>)
_CCCL_API constexpr explicit span(_Range&& __r)
: __data_{::cuda::std::ranges::__data_cpo{}(__r)}
{
_CCCL_ASSERT(::cuda::std::ranges::__size_cpo{}(__r) == _Extent, "size mismatch in span's constructor (range)");
}
// NOLINTEND(bugprone-forwarding-reference-overload)
// Deviation from P4144R1 Hana Dusikova's proposed fix: uses initializer_list<_InitListValueType>
// instead of initializer_list<const _InitListValueType>. The const is redundant because
// initializer_list<T>::begin() already returns const T*, so initializer_list<const T>::begin()
// returns const const T* which collapses to const T* — identical behavior. Omitting the const
// also avoids complications with template argument deduction in the CCCL SFINAE fallback path.
_CCCL_TEMPLATE(class _InitListValueType, class _Ep = element_type)
_CCCL_REQUIRES(is_same_v<_InitListValueType, value_type> _CCCL_AND is_const_v<_Ep>)
_CCCL_API constexpr span(initializer_list<_InitListValueType> __il)
: __data_{__il.begin()}
{
_CCCL_ASSERT(_Extent == __il.size(), "size mismatch in span's constructor (initializer_list)");
}
_CCCL_TEMPLATE(class _OtherElementType, size_t _Extent2 = _Extent)
_CCCL_REQUIRES((_Extent2 != dynamic_extent) _CCCL_AND __span_array_convertible<_OtherElementType, element_type>)
_CCCL_API constexpr span(const span<_OtherElementType, _Extent2>& __other) noexcept
: __data_{__other.data()}
{}
_CCCL_TEMPLATE(class _OtherElementType)
_CCCL_REQUIRES(__span_array_convertible<_OtherElementType, element_type>)
_CCCL_API constexpr explicit span(const span<_OtherElementType, dynamic_extent>& __other) noexcept
: __data_{__other.data()}
{
_CCCL_ASSERT(_Extent == __other.size(), "size mismatch in span's constructor (other span)");
}
// ~span() noexcept = default;
template <size_t _Count>
_CCCL_API constexpr span<element_type, _Count> first() const noexcept
{
// ternary avoids "pointless comparison of unsigned integer with zero" warning
static_assert(_Count == 0 ? true : _Count <= _Extent, "span<T, N>::first<Count>(): Count out of range");
return span<element_type, _Count>{data(), _Count};
}
template <size_t _Count>
_CCCL_API constexpr span<element_type, _Count> last() const noexcept
{
// ternary avoids "pointless comparison of unsigned integer with zero" warning
static_assert(_Count == 0 ? true : _Count <= _Extent, "span<T, N>::last<Count>(): Count out of range");
return span<element_type, _Count>{data() + size() - _Count, _Count};
}
_CCCL_API constexpr span<element_type, dynamic_extent> first(size_type __count) const noexcept
{
_CCCL_ASSERT(__count <= size(), "span<T, N>::first(count): count out of range");
return {data(), __count};
}
_CCCL_API constexpr span<element_type, dynamic_extent> last(size_type __count) const noexcept
{
_CCCL_ASSERT(__count <= size(), "span<T, N>::last(count): count out of range");
return {data() + size() - __count, __count};
}
template <size_t _Offset, size_t _Count>
using __subspan_t = span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset>;
template <size_t _Offset, size_t _Count = dynamic_extent>
_CCCL_API constexpr __subspan_t<_Offset, _Count> subspan() const noexcept
{
// ternary avoids "pointless comparison of unsigned integer with zero" warning
if constexpr (_Offset != 0)
{
static_assert(_Offset <= _Extent, "span<T, N>::subspan<Offset, Count>(): Offset out of range");
}
if constexpr (_Count != 0)
{
static_assert(_Count == dynamic_extent || _Count <= _Extent - _Offset,
"span<T, N>::subspan<Offset, Count>(): Offset + Count out of range");
}
return __subspan_t<_Offset, _Count>{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
}
_CCCL_API constexpr span<element_type, dynamic_extent>
subspan(size_type __offset, size_type __count = dynamic_extent) const noexcept
{
_CCCL_ASSERT(__offset <= size(), "span<T, N>::subspan(offset, count): offset out of range");
_CCCL_ASSERT(__count <= size() || __count == dynamic_extent,
"span<T, N>::subspan(offset, count): count out of range");
if (__count == dynamic_extent)
{
return {data() + __offset, size() - __offset};
}
_CCCL_ASSERT(__count <= size() - __offset, "span<T, N>::subspan(offset, count): offset + count out of range");
return {data() + __offset, __count};
}
_CCCL_API constexpr size_type size() const noexcept
{
return _Extent;
}
_CCCL_API constexpr size_type size_bytes() const noexcept
{
return _Extent * sizeof(element_type);
}
[[nodiscard]] _CCCL_API constexpr bool empty() const noexcept
{
return _Extent == 0;
}
_CCCL_API constexpr reference operator[](size_type __idx) const noexcept
{
_CCCL_ASSERT(__idx < size(), "span<T, N>::operator[](index): index out of range");
return __data_[__idx];
}
_CCCL_API constexpr reference at(size_type __idx) const
{
if (__idx >= size())
{
_CCCL_THROW(::std::out_of_range, "span::at");
}
return __data_[__idx];
}
_CCCL_API constexpr reference front() const noexcept
{
_CCCL_ASSERT(!empty(), "span<T, N>::front() on empty span");
return __data_[0];
}
_CCCL_API constexpr reference back() const noexcept
{
_CCCL_ASSERT(!empty(), "span<T, N>::back() on empty span");
return __data_[size() - 1];
}
_CCCL_API constexpr pointer data() const noexcept
{
return __data_;
}
// [span.iter], span iterator support
_CCCL_API constexpr iterator begin() const noexcept
{
return iterator(data());
}
_CCCL_API constexpr iterator end() const noexcept
{
return iterator(data() + size());
}
_CCCL_API constexpr reverse_iterator rbegin() const noexcept
{
return reverse_iterator(end());
}
_CCCL_API constexpr reverse_iterator rend() const noexcept
{
return reverse_iterator(begin());
}
_CCCL_API inline span<const byte, _Extent * sizeof(element_type)> __as_bytes() const noexcept
{
return span<const byte, _Extent * sizeof(element_type)>{reinterpret_cast<const byte*>(data()), size_bytes()};
}
_CCCL_API inline span<byte, _Extent * sizeof(element_type)> __as_writable_bytes() const noexcept
{
return span<byte, _Extent * sizeof(element_type)>{reinterpret_cast<byte*>(data()), size_bytes()};
}
private:
pointer __data_;
};
template <typename _Tp>
class _CCCL_TYPE_VISIBILITY_DEFAULT span<_Tp, dynamic_extent>
{
public:
// constants and types
using element_type = _Tp;
using value_type = remove_cv_t<_Tp>;
using size_type = size_t;
using difference_type = ptrdiff_t;
using pointer = _Tp*;
using const_pointer = const _Tp*;
using reference = _Tp&;
using const_reference = const _Tp&;
using iterator = __wrap_iter<pointer>;
using reverse_iterator = ::cuda::std::reverse_iterator<iterator>;
static constexpr size_type extent = dynamic_extent;
// [span.cons], span constructors, copy, assignment, and destructor
_CCCL_API constexpr span() noexcept
: __data_{nullptr}
, __size_{0}
{}
_CCCL_HIDE_FROM_ABI span(const span&) noexcept = default;
_CCCL_HIDE_FROM_ABI span& operator=(const span&) noexcept = default;
_CCCL_EXEC_CHECK_DISABLE
_CCCL_TEMPLATE(class _It)
_CCCL_REQUIRES(__span_compatible_iterator<_It, element_type>)
_CCCL_API constexpr span(_It __first, size_type __count)
: __data_{::cuda::std::to_address(__first)}
, __size_{__count}
{}
_CCCL_EXEC_CHECK_DISABLE
_CCCL_TEMPLATE(class _It, class _End)
_CCCL_REQUIRES(__span_compatible_iterator<_It, element_type> _CCCL_AND __span_compatible_sentinel_for<_End, _It>)
_CCCL_API constexpr span(_It __first, _End __last)
: __data_(::cuda::std::to_address(__first))
, __size_(__last - __first)
{
_CCCL_ASSERT(__last - __first >= 0, "invalid range in span's constructor (iterator, sentinel)");
}
template <size_t _Sz>
_CCCL_API constexpr span(type_identity_t<element_type> (&__arr)[_Sz]) noexcept
: __data_{__arr}
, __size_{_Sz}
{}
_CCCL_TEMPLATE(class _OtherElementType, size_t _Sz)
_CCCL_REQUIRES(__span_array_convertible<_OtherElementType, element_type>)
_CCCL_API constexpr span(array<_OtherElementType, _Sz>& __arr) noexcept
: __data_{__arr.data()}
, __size_{_Sz}
{}
_CCCL_TEMPLATE(class _OtherElementType, size_t _Sz)
_CCCL_REQUIRES(__span_array_convertible<const _OtherElementType, element_type>)
_CCCL_API constexpr span(const array<_OtherElementType, _Sz>& __arr) noexcept
: __data_{__arr.data()}
, __size_{_Sz}
{}
#if _CCCL_HAS_HOST_STD_LIB()
_CCCL_TEMPLATE(class _OtherElementType, size_t _Sz)
_CCCL_REQUIRES(__span_array_convertible<_OtherElementType, element_type>)
_CCCL_HOST_API constexpr span(::std::array<_OtherElementType, _Sz>& __arr) noexcept
: __data_{__arr.data()}
, __size_{_Sz}
{}
_CCCL_TEMPLATE(class _OtherElementType, size_t _Sz)
_CCCL_REQUIRES(__span_array_convertible<const _OtherElementType, element_type>)
_CCCL_HOST_API constexpr span(const ::std::array<_OtherElementType, _Sz>& __arr) noexcept
: __data_{__arr.data()}
, __size_{_Sz}
{}
#endif // _CCCL_HAS_HOST_STD_LIB()
// NOLINTBEGIN(bugprone-forwarding-reference-overload)
_CCCL_EXEC_CHECK_DISABLE
_CCCL_TEMPLATE(class _Range)
_CCCL_REQUIRES(__span_compatible_range<_Range, element_type>)
_CCCL_API constexpr span(_Range&& __r)
: __data_(::cuda::std::ranges::__data_cpo{}(__r))
, __size_{::cuda::std::ranges::__size_cpo{}(__r)}
{}
// NOLINTEND(bugprone-forwarding-reference-overload)
// Deviation from P4144R1 Hana Dusikova's proposed fix: uses initializer_list<_InitListValueType>
// instead of initializer_list<const _InitListValueType>. The const is redundant because
// initializer_list<T>::begin() already returns const T*, so initializer_list<const T>::begin()
// returns const const T* which collapses to const T* — identical behavior. Omitting the const
// also avoids complications with template argument deduction in the CCCL SFINAE fallback path.
_CCCL_TEMPLATE(class _InitListValueType, class _Ep = element_type)
_CCCL_REQUIRES(is_same_v<_InitListValueType, value_type> _CCCL_AND is_const_v<_Ep>)
_CCCL_API constexpr span(initializer_list<_InitListValueType> __il)
: __data_{__il.begin()}
, __size_{__il.size()}
{}
_CCCL_TEMPLATE(class _OtherElementType, size_t _OtherExtent)
_CCCL_REQUIRES(__span_array_convertible<_OtherElementType, element_type>)
_CCCL_API constexpr span(const span<_OtherElementType, _OtherExtent>& __other) noexcept
: __data_{__other.data()}
, __size_{__other.size()}
{}
// ~span() noexcept = default;
template <size_t _Count>
_CCCL_API constexpr span<element_type, _Count> first() const noexcept
{
// ternary avoids "pointless comparison of unsigned integer with zero" warning
_CCCL_ASSERT(_Count == 0 ? true : _Count <= size(), "span<T>::first<Count>(): Count out of range");
return span<element_type, _Count>{data(), _Count};
}
template <size_t _Count>
_CCCL_API constexpr span<element_type, _Count> last() const noexcept
{
// ternary avoids "pointless comparison of unsigned integer with zero" warning
_CCCL_ASSERT(_Count == 0 ? true : _Count <= size(), "span<T>::last<Count>(): Count out of range");
return span<element_type, _Count>{data() + size() - _Count, _Count};
}
_CCCL_API constexpr span<element_type, dynamic_extent> first(size_type __count) const noexcept
{
_CCCL_ASSERT(__count <= size(), "span<T>::first(count): count out of range");
return {data(), __count};
}
_CCCL_API constexpr span<element_type, dynamic_extent> last(size_type __count) const noexcept
{
_CCCL_ASSERT(__count <= size(), "span<T>::last(count): count out of range");
return {data() + size() - __count, __count};
}
template <size_t _Offset, size_t _Count>
using __subspan_t = span<element_type, _Count>;
template <size_t _Offset, size_t _Count = dynamic_extent>
_CCCL_API constexpr __subspan_t<_Offset, _Count> subspan() const noexcept
{
// ternary avoids "pointless comparison of unsigned integer with zero" warning
_CCCL_ASSERT(_Offset == 0 ? true : _Offset <= size(), "span<T>::subspan<Offset, Count>(): Offset out of range");
_CCCL_ASSERT(_Count == dynamic_extent || (_Count == 0 ? true : _Count <= size() - _Offset),
"span<T>::subspan<Offset, Count>(): Offset + Count out of range");
return __subspan_t<_Offset, _Count>{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
}
constexpr span<element_type, dynamic_extent> _CCCL_API inline subspan(
size_type __offset, size_type __count = dynamic_extent) const noexcept
{
_CCCL_ASSERT(__offset <= size(), "span<T>::subspan(offset, count): offset out of range");
_CCCL_ASSERT(__count <= size() || __count == dynamic_extent, "span<T>::subspan(offset, count): count out of range");
if (__count == dynamic_extent)
{
return {data() + __offset, size() - __offset};
}
_CCCL_ASSERT(__count <= size() - __offset, "span<T>::subspan(offset, count): offset + count out of range");
return {data() + __offset, __count};
}
_CCCL_API constexpr size_type size() const noexcept
{
return __size_;
}
_CCCL_API constexpr size_type size_bytes() const noexcept
{
return __size_ * sizeof(element_type);
}
[[nodiscard]] _CCCL_API constexpr bool empty() const noexcept
{
return __size_ == 0;
}
_CCCL_API constexpr reference operator[](size_type __idx) const noexcept
{
_CCCL_ASSERT(__idx < size(), "span<T>::operator[](index): index out of range");
return __data_[__idx];
}
_CCCL_API constexpr reference at(size_type __idx) const
{
if (__idx >= size())
{
_CCCL_THROW(::std::out_of_range, "span::at");
}
return __data_[__idx];
}
_CCCL_API constexpr reference front() const noexcept
{
_CCCL_ASSERT(!empty(), "span<T>::front() on empty span");
return __data_[0];
}
_CCCL_API constexpr reference back() const noexcept
{
_CCCL_ASSERT(!empty(), "span<T>::back() on empty span");
return __data_[size() - 1];
}
_CCCL_API constexpr pointer data() const noexcept
{
return __data_;
}
// [span.iter], span iterator support
_CCCL_API constexpr iterator begin() const noexcept
{
return iterator(data());
}
_CCCL_API constexpr iterator end() const noexcept
{
return iterator(data() + size());
}
_CCCL_API constexpr reverse_iterator rbegin() const noexcept
{
return reverse_iterator(end());
}
_CCCL_API constexpr reverse_iterator rend() const noexcept
{
return reverse_iterator(begin());
}
_CCCL_API inline span<const byte, dynamic_extent> __as_bytes() const noexcept
{
return span<const byte, dynamic_extent>{reinterpret_cast<const byte*>(data()), size_bytes()};
}
_CCCL_API inline span<byte, dynamic_extent> __as_writable_bytes() const noexcept
{
return span<byte, dynamic_extent>{reinterpret_cast<byte*>(data()), size_bytes()};
}
private:
pointer __data_;
size_type __size_;
};
// as_bytes & as_writable_bytes
template <class _Tp, size_t _Extent>
_CCCL_API inline auto as_bytes(span<_Tp, _Extent> __s) noexcept
{
return __s.__as_bytes();
}
_CCCL_TEMPLATE(class _Tp, size_t _Extent)
_CCCL_REQUIRES((!is_const<_Tp>::value))
_CCCL_API inline auto as_writable_bytes(span<_Tp, _Extent> __s) noexcept
{
return __s.__as_writable_bytes();
}
// Deduction guides
template <class _Tp, size_t _Sz>
_CCCL_DEDUCTION_GUIDE_ATTRIBUTES span(_Tp (&)[_Sz]) -> span<_Tp, _Sz>;
template <class _Tp, size_t _Sz>
_CCCL_DEDUCTION_GUIDE_ATTRIBUTES span(array<_Tp, _Sz>&) -> span<_Tp, _Sz>;
template <class _Tp, size_t _Sz>
_CCCL_DEDUCTION_GUIDE_ATTRIBUTES span(const array<_Tp, _Sz>&) -> span<const _Tp, _Sz>;
#if _CCCL_HAS_HOST_STD_LIB()
template <class _Tp, size_t _Sz>
_CCCL_DEDUCTION_GUIDE_ATTRIBUTES span(::std::array<_Tp, _Sz>&) -> span<_Tp, _Sz>;
template <class _Tp, size_t _Sz>
_CCCL_DEDUCTION_GUIDE_ATTRIBUTES span(const ::std::array<_Tp, _Sz>&) -> span<const _Tp, _Sz>;
#endif // _CCCL_HAS_HOST_STD_LIB()
_CCCL_TEMPLATE(class _It, class _EndOrSize)
_CCCL_REQUIRES(contiguous_iterator<_It>)
_CCCL_DEDUCTION_GUIDE_ATTRIBUTES span(_It, _EndOrSize)
-> span<remove_reference_t<iter_reference_t<_It>>, __maybe_static_ext<_EndOrSize>>;
_CCCL_TEMPLATE(class _Range)
_CCCL_REQUIRES(::cuda::std::ranges::contiguous_range<_Range>)
_CCCL_DEDUCTION_GUIDE_ATTRIBUTES span(_Range&&)
-> span<remove_reference_t<::cuda::std::ranges::range_reference_t<_Range>>>;
_CCCL_END_NAMESPACE_CUDA_STD
_CCCL_BEGIN_NAMESPACE_CUDA_STD_RANGES
template <class _Tp, size_t _Extent>
inline constexpr bool enable_borrowed_range<span<_Tp, _Extent>> = true;
template <class _Tp, size_t _Extent>
inline constexpr bool enable_view<span<_Tp, _Extent>> = true;
_CCCL_END_NAMESPACE_CUDA_STD_RANGES
#include <cuda/std/__cccl/epilogue.h>
#endif // _CUDA_STD_SPAN