diff options
Diffstat (limited to 'libstdc++-v3/include/std')
| -rw-r--r-- | libstdc++-v3/include/std/charconv | 6 | ||||
| -rw-r--r-- | libstdc++-v3/include/std/concepts | 23 | ||||
| -rw-r--r-- | libstdc++-v3/include/std/latch | 2 | ||||
| -rw-r--r-- | libstdc++-v3/include/std/mdspan | 723 | ||||
| -rw-r--r-- | libstdc++-v3/include/std/type_traits | 13 | ||||
| -rw-r--r-- | libstdc++-v3/include/std/utility | 72 | ||||
| -rw-r--r-- | libstdc++-v3/include/std/variant | 34 |
7 files changed, 723 insertions, 150 deletions
diff --git a/libstdc++-v3/include/std/charconv b/libstdc++-v3/include/std/charconv index 8cf2c0b..47f5aaa 100644 --- a/libstdc++-v3/include/std/charconv +++ b/libstdc++-v3/include/std/charconv @@ -554,10 +554,10 @@ namespace __detail } // namespace __detail - /// std::from_chars for integral types. + /// std::from_chars for integer types. template<typename _Tp, - enable_if_t<__or_<__is_standard_integer<_Tp>, - is_same<char, remove_cv_t<_Tp>>>::value, int> = 0> + enable_if_t<__or_<__is_signed_or_unsigned_integer<_Tp>, + is_same<char, _Tp>>::value, int> = 0> _GLIBCXX23_CONSTEXPR from_chars_result from_chars(const char* __first, const char* __last, _Tp& __value, int __base = 10) diff --git a/libstdc++-v3/include/std/concepts b/libstdc++-v3/include/std/concepts index d9920a8..870b0a4 100644 --- a/libstdc++-v3/include/std/concepts +++ b/libstdc++-v3/include/std/concepts @@ -296,6 +296,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { { !static_cast<_Tp&&>(__t) } -> __boolean_testable_impl; }; } // namespace __detail + // [concept.comparisoncommontype], helpers for comparison common types + namespace __detail + { + template<typename _Tp, typename _Up, + typename _Cref = common_reference_t<const _Tp&, const _Up&>> + concept __comparison_common_type_with_impl + = same_as<common_reference_t<const _Tp&, const _Up&>, + common_reference_t<const _Up&, const _Tp&>> + && requires { + requires convertible_to<const _Tp&, const _Cref&> + || convertible_to<_Tp, const _Cref&>; + requires convertible_to<const _Up&, const _Cref&> + || convertible_to<_Up, const _Cref&>; + }; + + template<typename _Tp, typename _Up> + concept __comparison_common_type_with + = __comparison_common_type_with_impl<remove_cvref_t<_Tp>, + remove_cvref_t<_Up>>; + } // namespace __detail + // [concept.equalitycomparable], concept equality_comparable namespace __detail @@ -316,7 +337,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp, typename _Up> concept equality_comparable_with = equality_comparable<_Tp> && equality_comparable<_Up> - && common_reference_with<__detail::__cref<_Tp>, __detail::__cref<_Up>> + && __detail::__comparison_common_type_with<_Tp, _Up> && equality_comparable<common_reference_t<__detail::__cref<_Tp>, __detail::__cref<_Up>>> && __detail::__weakly_eq_cmp_with<_Tp, _Up>; diff --git a/libstdc++-v3/include/std/latch b/libstdc++-v3/include/std/latch index 9504df0..df126c6 100644 --- a/libstdc++-v3/include/std/latch +++ b/libstdc++-v3/include/std/latch @@ -41,7 +41,7 @@ #ifdef __cpp_lib_latch // C++ >= 20 && atomic_wait #include <bits/atomic_base.h> #include <ext/numeric_traits.h> -#include <utility> // cmp_equal, cmp_less_equal, etc. +#include <bits/intcmp.h> // cmp_equal, cmp_less_equal, etc. namespace std _GLIBCXX_VISIBILITY(default) { diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan index 03cc4f0..dc0aa4f 100644 --- a/libstdc++-v3/include/std/mdspan +++ b/libstdc++-v3/include/std/mdspan @@ -271,7 +271,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION requires (_Extents.size() > 0) { return {_M_dyn_exts + _S_dynamic_index(__begin), - _M_dyn_exts + _S_dynamic_index(__end)}; + _S_dynamic_index(__end) - _S_dynamic_index(__begin)}; } private: @@ -352,11 +352,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _OffsetType, typename _ExtentType, typename _StrideType> struct strided_slice { - static_assert(__is_standard_integer<_OffsetType>::value + static_assert(__is_signed_or_unsigned_integer<_OffsetType>::value || __detail::__integral_constant_like<_OffsetType>); - static_assert(__is_standard_integer<_ExtentType>::value + static_assert(__is_signed_or_unsigned_integer<_ExtentType>::value || __detail::__integral_constant_like<_ExtentType>); - static_assert(__is_standard_integer<_StrideType>::value + static_assert(__is_signed_or_unsigned_integer<_StrideType>::value || __detail::__integral_constant_like<_StrideType>); using offset_type = _OffsetType; @@ -374,12 +374,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION [[no_unique_address]] _Mapping mapping = _Mapping(); size_t offset{}; }; + + template<typename _Tp> + constexpr bool __is_submdspan_mapping_result = false; + + template<typename _Mapping> + constexpr bool __is_submdspan_mapping_result<submdspan_mapping_result<_Mapping>> = true; + + template<typename _Mapping> + concept __submdspan_mapping_result = __is_submdspan_mapping_result<_Mapping>; + #endif // __glibcxx_submdspan template<typename _IndexType, size_t... _Extents> class extents { - static_assert(__is_standard_integer<_IndexType>::value, + static_assert(__is_signed_or_unsigned_integer<_IndexType>::value, "IndexType must be a signed or unsigned integer type"); static_assert( (__mdspan::__valid_static_extent<_Extents, _IndexType> && ...), @@ -589,6 +599,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } } + template<typename _IndexType, size_t _Nm> + consteval _IndexType + __fwd_prod(span<const _IndexType, _Nm> __values) + { + _IndexType __ret = 1; + for(auto __value : __values) + __ret *= __value; + return __ret; + } + // Preconditions: _r < _Extents::rank() template<typename _Extents> constexpr typename _Extents::index_type @@ -792,6 +812,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Mapping> constexpr bool __is_right_padded_mapping = __padded_mapping_of< layout_right_padded, _Mapping>; + + template<typename _Mapping> + constexpr bool __is_padded_mapping = __is_left_padded_mapping<_Mapping> + || __is_right_padded_mapping<_Mapping>; #endif template<typename _PaddedMapping> @@ -866,6 +890,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __exts.extent(_Index)}; } + template<typename _Slice, typename _IndexType> + concept __acceptable_slice_type = same_as<_Slice, full_extent_t> + || same_as<_Slice, _IndexType> || __is_constant_wrapper<_Slice> + || __is_strided_slice<_Slice>; + template<typename _IndexType, typename... _Slices> consteval auto __subrank() @@ -890,6 +919,547 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __map[__i++] = __k; return __map; } + + template<typename _Slice> + constexpr auto + __slice_begin(_Slice __slice) + { + if constexpr (same_as<_Slice, full_extent_t>) + return 0; + else if constexpr (__is_strided_slice<_Slice>) + return __slice.offset; + else + return __slice; // collapsing slice + } + + template<typename _Mapping, typename... _Slices> + constexpr size_t + __suboffset(const _Mapping& __mapping, const _Slices&... __slices) + { + using _IndexType = typename _Mapping::index_type; + auto __any_past_the_end = [&]<size_t... _Is>(index_sequence<_Is...>) + { + auto __is_past_the_end = [](const auto& __slice, const auto& __ext) + { + using _Slice = remove_cvref_t<decltype(__slice)>; + if constexpr (is_convertible_v<_Slice, _IndexType>) + return false; + else if constexpr (same_as<_Slice, full_extent_t> + && __ext.static_extent(0) != 0 + && __ext.static_extent(0) != dynamic_extent) + return false; + else + return __mdspan::__slice_begin(__slice) == __ext.extent(0); + }; + + const auto& __exts = __mapping.extents(); + return ((__is_past_the_end(__slices...[_Is], + __mdspan::__extract_extent<_Is>(__exts))) || ...); + }; + + if constexpr ((same_as<_Slices, full_extent_t> && ...)) + return __mdspan::__offset(__mapping); + + if (__any_past_the_end(std::make_index_sequence<sizeof...(__slices)>())) + return __mapping.required_span_size(); + return __mapping(__mdspan::__slice_begin(__slices)...); + } + + template<typename _IndexType, size_t _Extent, typename _Slice> + consteval size_t + __static_slice_extent() + { + if constexpr (same_as<_Slice, full_extent_t>) + return _Extent; + else if constexpr (same_as<_Slice, constant_wrapper<_IndexType(0)>>) + return 0; + else if constexpr (__is_constant_wrapper<typename _Slice::extent_type> + && __is_constant_wrapper<typename _Slice::stride_type>) + return 1 + ((typename _Slice::extent_type{}) - 1) + / (typename _Slice::stride_type{}); + else + return dynamic_extent; + } + + template<size_t _K, typename _Extents, typename _Slice> + constexpr typename _Extents::index_type + __dynamic_slice_extent(const _Extents& __exts, _Slice __slice) + { + if constexpr (__is_strided_slice<_Slice>) + return __slice.extent == 0 ? 0 : 1 + (__slice.extent - 1) / __slice.stride; + else + return __exts.extent(_K); + } + + template<typename _IndexType, size_t... _Extents, typename... _Slices> + requires (sizeof...(_Slices) == sizeof...(_Extents)) + constexpr auto + __subextents(const extents<_IndexType, _Extents...>& __exts, + _Slices... __slices) + { + constexpr auto __inv_map = __mdspan::__inv_map_rank<_IndexType, _Slices...>(); + auto __impl = [&]<size_t... _Indices>(std::index_sequence<_Indices...>) + { + using _SubExts = extents<_IndexType, + __mdspan::__static_slice_extent<_IndexType, + _Extents...[__inv_map[_Indices]], + _Slices...[__inv_map[_Indices]]>()...>; + if constexpr (_SubExts::rank_dynamic() == 0) + return _SubExts{}; + else + { + using _StaticSubExtents = __mdspan::_StaticExtents< + __mdspan::__static_extents<_SubExts>()>; + auto __create = [&]<size_t... _Is>(std::index_sequence<_Is...>) + { + constexpr auto __slice_idx = [__inv_map](size_t __i) consteval + { + return __inv_map[_StaticSubExtents::_S_dynamic_index_inv(__i)]; + }; + + return _SubExts{__mdspan::__dynamic_slice_extent<__slice_idx(_Is)>( + __exts, __slices...[__slice_idx(_Is)])...}; + }; + constexpr auto __dyn_subrank = _SubExts::rank_dynamic(); + return __create(std::make_index_sequence<__dyn_subrank>()); + } + }; + + return __impl(std::make_index_sequence<__inv_map.size()>()); + } + + enum class _LayoutSide + { + __left, + __right, + __unknown + }; + + template<typename _Mapping> + consteval _LayoutSide + __mapping_side() + { + if constexpr (__is_left_padded_mapping<_Mapping> + || __mapping_of<layout_left, _Mapping>) + return _LayoutSide::__left; + if constexpr (__is_right_padded_mapping<_Mapping> + || __mapping_of<layout_right, _Mapping>) + return _LayoutSide::__right; + else + return _LayoutSide::__unknown; + } + + template<_LayoutSide _Side, size_t _Rank> + struct _StridesTrait + { + static constexpr const _LayoutSide _S_side = _Side; + + static constexpr size_t + _S_idx(size_t __k) noexcept + { + if constexpr (_Side == _LayoutSide::__left) + return __k; + else + return _Rank - 1 - __k; + } + + // Unifies the formulas for computing strides for padded and unpadded + // layouts. + template<typename _Mapping> + static constexpr typename _Mapping::index_type + _S_padded_extent(const _Mapping& __mapping, size_t __k) + { + if (__k == 0) + return __mapping.stride(_S_idx(1)); + else + return __mapping.extents().extent(_S_idx(__k)); + } + + template<typename _IndexType, typename... _Slices> + static consteval auto + _S_inv_map() + { + static_assert(_Side != _LayoutSide::__unknown); + auto __impl = [&]<size_t... _Is>(std::index_sequence<_Is...>) + { + return __mdspan::__inv_map_rank<_IndexType, _Slices...[_S_idx(_Is)]...>(); + }; + return __impl(std::make_index_sequence<_Rank>()); + } + }; + + template<typename _SubExts, typename _Mapping, typename... _Slices> + constexpr auto + __substrides_generic(const _Mapping& __mapping, const _Slices&... __slices) + { + using _IndexType = typename _Mapping::index_type; + if constexpr (_SubExts::rank() == 0) + return array<_IndexType, _SubExts::rank()>{}; + else + { + auto __stride = [&__mapping](size_t __k, auto __slice) -> _IndexType + { + if constexpr (__is_strided_slice<decltype(__slice)>) + if (__slice.stride < __slice.extent) + return __mapping.stride(__k) * __slice.stride; + return __mapping.stride(__k); + }; + + auto __impl = [&]<size_t... _Is>(std::index_sequence<_Is...>) + { + constexpr auto __inv_map + = __mdspan::__inv_map_rank<_IndexType, _Slices...>(); + return array<_IndexType, _SubExts::rank()>{ + __stride(__inv_map[_Is], __slices...[__inv_map[_Is]])...}; + }; + return __impl(std::make_index_sequence<_SubExts::rank()>()); + } + }; + + template<typename _SubExts, typename _Mapping, typename... _Slices> + constexpr auto + __substrides_standardized(const _Mapping& __mapping, + const _Slices&... __slices) + { + using _IndexType = typename _Mapping::index_type; + using _Trait = _StridesTrait<__mapping_side<_Mapping>(), + _Mapping::extents_type::rank()>; + using _SubTrait = _StridesTrait<__mapping_side<_Mapping>(), _SubExts::rank()>; + + constexpr size_t __sub_rank = _SubExts::rank(); + + std::array<_IndexType, __sub_rank> __ret; + if constexpr (__sub_rank > 0) + { + constexpr auto __inv_map + = _Trait::template _S_inv_map<_IndexType, _Slices...>(); + auto __loop = [&]<size_t... _Ks>(std::index_sequence<_Ks...>) + { + size_t __i0 = 0; + size_t __stride = 1; + auto __body = [&](size_t __k, auto __slice) + { + for (size_t __i = __i0; __i < __inv_map[__k]; ++__i) + __stride *= _Trait::_S_padded_extent(__mapping, __i); + + size_t __krev = _SubTrait::_S_idx(__k); + if constexpr (__is_strided_slice<decltype(__slice)>) + { + if (__slice.stride < __slice.extent) + __ret[__krev] = __stride * __slice.stride; + else + __ret[__krev] = __stride; + } + else + __ret[__krev] = __stride; + + __i0 = __inv_map[__k]; + }; + + ((__body(_Ks, __slices...[_Trait::_S_idx(__inv_map[_Ks])])),...); + }; + __loop(std::make_index_sequence<__sub_rank>()); + } + return __ret; + } + + + template<typename _SubExts, typename _Mapping, typename... _Slices> + constexpr auto + __substrides(const _Mapping& __mapping, const _Slices&... __slices) + { + if constexpr (__mdspan::__mapping_side<_Mapping>() == _LayoutSide::__unknown) + return __mdspan::__substrides_generic<_SubExts>(__mapping, __slices...); + else + return __mdspan::__substrides_standardized<_SubExts>(__mapping, __slices...); + } + + template<typename _Slice> + concept __is_unit_stride_slice = (__mdspan::__is_strided_slice<_Slice> + && __mdspan::__is_constant_wrapper<typename _Slice::stride_type> + && _Slice::stride_type::value == 1) + || std::same_as<_Slice, full_extent_t>; + + // These are (forced) exclusive categories: + // - full & collapsing: obvious, + // - unit_strided_slice: strided_slice{a, b, cw<1>}, but not `full`, + // - strided_slice: strided_slice{a, b, c} with c != cw<1>. + enum class _SliceKind + { + __strided_slice, + __unit_strided_slice, + __full, + __collapsing + }; + + template<typename _Slice> + consteval _SliceKind + __make_slice_kind() + { + if constexpr (std::same_as<_Slice, full_extent_t>) + return _SliceKind::__full; + else if constexpr (__mdspan::__is_strided_slice<_Slice>) + { + if constexpr (__mdspan::__is_unit_stride_slice<_Slice>) + return _SliceKind::__unit_strided_slice; + else + return _SliceKind::__strided_slice; + } + else + return _SliceKind::__collapsing; + } + + template<typename... _Slices> + consteval array<_SliceKind, sizeof...(_Slices)> + __make_slice_kind_array() + { + return array<_SliceKind, sizeof...(_Slices)>{ + __mdspan::__make_slice_kind<_Slices>()...}; + } + + // __block_size - 1 + // [full, ..., full, unit_slice , *] + consteval bool + __is_block(span<const _SliceKind> __slice_kinds, size_t __block_size) + { + if (__block_size == 0) + return false; + + if (__block_size > __slice_kinds.size()) + return false; + + for (size_t __i = 0; __i < __block_size - 1; ++__i) + if (__slice_kinds[__i] != _SliceKind::__full) + return false; + + auto __last = __slice_kinds[__block_size - 1]; + return __last == _SliceKind::__full + || __last == _SliceKind::__unit_strided_slice; + } + + // __u __u + __sub_rank-2 + // [unit_slice, i, ..., k, full, ..., full, unit_slice, *] + static consteval size_t + __padded_block_begin_generic(span<const _SliceKind> __slice_kinds, + size_t __sub_rank) + { + if (__slice_kinds[0] != _SliceKind::__full + && __slice_kinds[0] != _SliceKind::__unit_strided_slice) + return dynamic_extent; + else if (__slice_kinds.size() == 1) + return dynamic_extent; + else + { + size_t __u = 1; + while(__u < __slice_kinds.size() + && __slice_kinds[__u] == _SliceKind::__collapsing) + ++__u; + + if (__mdspan::__is_block(__slice_kinds.subspan(__u), __sub_rank -1)) + return __u; + return dynamic_extent; + } + } + + template<_LayoutSide _Side, size_t _Nm> + static consteval size_t + __padded_block_begin(span<const _SliceKind, _Nm> __slice_kinds, size_t __sub_rank) + { + if constexpr (_Side == _LayoutSide::__left) + return __mdspan::__padded_block_begin_generic(__slice_kinds, __sub_rank); + else + { + std::array<_SliceKind, _Nm> __rev_slices; + for(size_t __i = 0; __i < _Nm; ++__i) + __rev_slices[__i] = __slice_kinds[_Nm - 1 - __i]; + auto __rev_slice_kinds = span<const _SliceKind>(__rev_slices); + + auto __u = __mdspan::__padded_block_begin_generic(__rev_slice_kinds, + __sub_rank); + return __u == dynamic_extent ? dynamic_extent : _Nm - 1 - __u; + } + } + + template<_LayoutSide _Side, bool _Padded> + struct _SubMdspanMapping; + + template<> + struct _SubMdspanMapping<_LayoutSide::__left, false> + { + using _Layout = layout_left; + template<size_t _Pad> using _PaddedLayout = layout_left_padded<_Pad>; + + template<typename _Mapping, size_t _Us> + static consteval size_t + _S_pad() + { + using _Extents = typename _Mapping::extents_type; + constexpr auto __sta_exts = __mdspan::__static_extents<_Extents>(0, _Us); + if constexpr (!__mdspan::__all_static(__sta_exts)) + return dynamic_extent; + else + return __mdspan::__fwd_prod(__sta_exts); + } + + template<size_t _Nm> + static consteval bool + _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds, size_t __sub_rank) + { return __mdspan::__is_block(__slice_kinds, __sub_rank); } + }; + + template<> + struct _SubMdspanMapping<_LayoutSide::__left, true> + { + using _Layout = layout_left; + template<size_t _Pad> using _PaddedLayout = layout_left_padded<_Pad>; + + template<typename _Mapping, size_t _Us> + static consteval size_t + _S_pad() + { + using _Extents = typename _Mapping::extents_type; + constexpr auto __sta_exts + = __mdspan::__static_extents<_Extents>(1, _Us); + constexpr auto __sta_padstride + = __mdspan::__get_static_stride<_Mapping>(); + if constexpr (__sta_padstride == dynamic_extent + || !__mdspan::__all_static(__sta_exts)) + return dynamic_extent; + else + return __sta_padstride * __mdspan::__fwd_prod(__sta_exts); + } + + template<size_t _Nm> + static consteval bool + _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds, + size_t __sub_rank) + { + if (__sub_rank == 1) + return __slice_kinds[0] == _SliceKind::__unit_strided_slice + || __slice_kinds[0] == _SliceKind::__full; + else + return false; + } + }; + + template<> + struct _SubMdspanMapping<_LayoutSide::__right, false> + { + using _Layout = layout_right; + template<size_t _Pad> using _PaddedLayout = layout_right_padded<_Pad>; + + template<typename _Mapping, size_t _Us> + static consteval size_t + _S_pad() + { + using _Extents = typename _Mapping::extents_type; + constexpr auto __rank = _Extents::rank(); + constexpr auto __sta_exts + = __mdspan::__static_extents<_Extents>(_Us + 1, __rank); + if constexpr (!__mdspan::__all_static(__sta_exts)) + return dynamic_extent; + else + return __fwd_prod(__sta_exts); + } + + template<size_t _Nm> + static consteval bool + _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds, + size_t __sub_rank) + { + auto __rev_slice_kinds = array<_SliceKind, _Nm>{}; + for(size_t __i = 0; __i < _Nm; ++__i) + __rev_slice_kinds[__i] = __slice_kinds[_Nm - 1 - __i]; + return __mdspan::__is_block(span(__rev_slice_kinds), __sub_rank); + } + }; + + template<> + struct _SubMdspanMapping<_LayoutSide::__right, true> + { + using _Layout = layout_right; + template<size_t _Pad> using _PaddedLayout = layout_right_padded<_Pad>; + + template<typename _Mapping, size_t _Us> + static consteval size_t + _S_pad() + { + using _Extents = typename _Mapping::extents_type; + constexpr auto __rank = _Extents::rank(); + constexpr auto __sta_exts + = __mdspan::__static_extents<_Extents>(_Us + 1, __rank - 1); + constexpr auto __sta_padstride + = __mdspan::__get_static_stride<_Mapping>(); + if constexpr (__sta_padstride == dynamic_extent + || !__mdspan::__all_static(__sta_exts)) + return dynamic_extent; + else + return __sta_padstride * __mdspan::__fwd_prod(__sta_exts); + } + + template<size_t _Nm> + static consteval bool + _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds, + size_t __sub_rank) + { + if (__sub_rank == 1) + return __slice_kinds[_Nm - 1] == _SliceKind::__unit_strided_slice + || __slice_kinds[_Nm - 1] == _SliceKind::__full; + else + return false; + } + }; + + + template<typename _Mapping> + constexpr auto + __submdspan_mapping_impl(const _Mapping& __mapping) + { return submdspan_mapping_result{__mapping, 0}; } + + template<typename _Mapping, typename... _Slices> + requires (sizeof...(_Slices) > 0) + constexpr auto + __submdspan_mapping_impl(const _Mapping& __mapping, _Slices... __slices) + { + using _IndexType = typename _Mapping::index_type; + static_assert((__acceptable_slice_type<_Slices, _IndexType> && ...)); + + constexpr auto __side = __mdspan::__mapping_side<_Mapping>(); + constexpr auto __rank = sizeof...(_Slices); + using _Trait = _SubMdspanMapping<__side, __is_padded_mapping<_Mapping>>; + using _SliceView = span<const _SliceKind, __rank>; + + constexpr auto __slice_kinds = __mdspan::__make_slice_kind_array<_Slices...>(); + auto __offset = __mdspan::__suboffset(__mapping, __slices...); + auto __sub_exts = __mdspan::__subextents(__mapping.extents(), __slices...); + using _SubExts = decltype(__sub_exts); + constexpr auto __sub_rank = _SubExts::rank(); + if constexpr (__sub_rank == 0) + return submdspan_mapping_result{ + typename _Trait::_Layout::mapping(__sub_exts), __offset}; + else if constexpr (_Trait::_S_is_unpadded_submdspan( + _SliceView(__slice_kinds), __sub_rank)) + return submdspan_mapping_result{ + typename _Trait::_Layout::mapping(__sub_exts), __offset}; + else if constexpr ( + constexpr auto __u = __padded_block_begin<__side>( + _SliceView(__slice_kinds), __sub_rank); + __u != dynamic_extent) + { + constexpr auto __pad = _Trait::template _S_pad<_Mapping, __u>(); + using _Layout = typename _Trait::template _PaddedLayout<__pad>; + return submdspan_mapping_result{ + typename _Layout::mapping(__sub_exts, __mapping.stride(__u)), + __offset}; + } + else + { + auto __sub_strides + = __mdspan::__substrides<_SubExts>(__mapping, __slices...); + return submdspan_mapping_result{ + layout_stride::mapping(__sub_exts, __sub_strides), __offset}; + } + } #endif // __glibcxx_submdspan } @@ -1032,6 +1602,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents)); } +#if __glibcxx_submdspan + template<typename... _Slices> + requires (extents_type::rank() == sizeof...(_Slices)) + friend constexpr auto + submdspan_mapping(const mapping& __mapping, _Slices... __slices) + { return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); } +#endif // __glibcxx_submdspan + [[no_unique_address]] extents_type _M_extents{}; }; @@ -1208,6 +1786,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents)); } +#if __glibcxx_submdspan + template<typename... _Slices> + requires (extents_type::rank() == sizeof...(_Slices)) + friend constexpr auto + submdspan_mapping(const mapping& __mapping, _Slices... __slices) + { return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); } +#endif // __glibcxx_submdspan + [[no_unique_address]] extents_type _M_extents{}; }; @@ -1418,6 +2004,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } private: +#if __glibcxx_submdspan + template<typename... _Slices> + requires (extents_type::rank() == sizeof...(_Slices)) + friend constexpr auto + submdspan_mapping(const mapping& __mapping, _Slices... __slices) + { + if constexpr (sizeof...(_Slices) == 0) + return submdspan_mapping_result{__mapping, 0}; + else + { + auto __offset = __mdspan::__suboffset(__mapping, __slices...); + auto __sub_exts = __mdspan::__subextents(__mapping.extents(), __slices...); + auto __sub_strides + = __mdspan::__substrides<decltype(__sub_exts)>(__mapping, __slices...); + return submdspan_mapping_result{ + layout_stride::mapping(__sub_exts, __sub_strides), __offset}; + } + } +#endif + using _Strides = typename __array_traits<index_type, extents_type::rank()>::_Type; [[no_unique_address]] extents_type _M_extents; @@ -2028,6 +2634,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator==(const mapping& __self, const _LeftpadMapping& __other) noexcept { return __self._M_storage._M_equal(__other); } + + private: +#if __glibcxx_submdspan + template<typename... _Slices> + requires (extents_type::rank() == sizeof...(_Slices)) + friend constexpr auto + submdspan_mapping(const mapping& __mapping, _Slices... __slices) + { return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); } +#endif // __glibcxx_submdspan }; template<size_t _PaddingValue> @@ -2197,6 +2812,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator==(const mapping& __self, const _RightPaddedMapping& __other) noexcept { return __self._M_storage._M_equal(__other); } + +#if __glibcxx_submdspan + private: + template<typename... _Slices> + requires (extents_type::rank() == sizeof...(_Slices)) + friend constexpr auto + submdspan_mapping(const mapping& __mapping, _Slices... __slices) + { return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); } +#endif // __glibcxx_submdspan }; #endif // __glibcxx_padded_layouts @@ -2700,68 +3324,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __impl(make_index_sequence<__rank>()); } - template<typename _IndexType, size_t _Extent, typename _Slice> - consteval size_t - __static_slice_extent() - { - if constexpr (same_as<_Slice, full_extent_t>) - return _Extent; - else if constexpr (same_as<_Slice, constant_wrapper<_IndexType(0)>>) - return 0; - else if constexpr (__is_constant_wrapper<typename _Slice::extent_type> - && __is_constant_wrapper<typename _Slice::stride_type>) - return 1 + ((typename _Slice::extent_type{}) - 1) - / (typename _Slice::stride_type{}); - else - return dynamic_extent; - } + template<typename _Slice> + using __full_extent_t = std::full_extent_t; - template<size_t _K, typename _Extents, typename _Slice> - constexpr typename _Extents::index_type - __dynamic_slice_extent(const _Extents& __exts, _Slice __slice) + // Enables ADL-only calls from submdspan. + void submdspan_mapping() = delete; + + template<typename _Mapping, typename... _Slices> + concept __sliceable_mapping = requires(const _Mapping __m, _Slices... __slices) { - if constexpr (__is_strided_slice<_Slice>) - return __slice.extent == 0 ? 0 : 1 + (__slice.extent - 1) / __slice.stride; - else - return __exts.extent(_K); - } + { submdspan_mapping(__m, __slices...) } -> __submdspan_mapping_result; + }; - template<typename _IndexType, size_t... _Extents, typename... _Slices> - requires (sizeof...(_Slices) == sizeof...(_Extents)) + template<typename _Mapping, typename... _Slices> constexpr auto - __subextents(const extents<_IndexType, _Extents...>& __exts, - _Slices... __slices) + __submapping(const _Mapping& __mapping, _Slices... __slices) { - constexpr auto __inv_map = __mdspan::__inv_map_rank<_IndexType, _Slices...>(); - auto __impl = [&]<size_t... _Indices>(index_sequence<_Indices...>) - { - using _SubExtents = extents<_IndexType, - (__mdspan::__static_slice_extent<_IndexType, - _Extents...[__inv_map[_Indices]], - _Slices...[__inv_map[_Indices]]>())...>; - if constexpr (_SubExtents::rank_dynamic() == 0) - return _SubExtents{}; - else - { - using _StaticSubExtents = __mdspan::_StaticExtents< - __mdspan::__static_extents<_SubExtents>()>; - auto __create = [&]<size_t... _Is>(index_sequence<_Is...>) - { - constexpr auto __slice_idx = [__inv_map](size_t __i) consteval - { - return __inv_map[_StaticSubExtents::_S_dynamic_index_inv(__i)]; - }; - - return _SubExtents{ - (__mdspan::__dynamic_slice_extent<__slice_idx(_Is)>( - __exts, __slices...[__slice_idx(_Is)]))...}; - }; - constexpr auto __dyn_subrank = _SubExtents::rank_dynamic(); - return __create(make_index_sequence<__dyn_subrank>()); - } - }; - - return __impl(make_index_sequence<__inv_map.size()>()); + __mdspan::__check_valid_slices(__mapping.extents(), __slices...); + return submdspan_mapping(__mapping, __slices...); } } @@ -2792,6 +3372,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; return __impl(__mdspan::__slice_cast<_IndexType>(__raw_slices)...); } + + template<typename _ElementType, typename _Extents, typename _Layout, + typename _Accessor, typename... _RawSlices> + requires (sizeof...(_RawSlices) == _Extents::rank() + && __mdspan::__sliceable_mapping<typename _Layout::mapping<_Extents>, + __mdspan::__full_extent_t<_RawSlices>...>) + constexpr auto + submdspan( + const mdspan<_ElementType, _Extents, _Layout, _Accessor>& __md, + _RawSlices... __raw_slices) + { + using _IndexType = typename _Extents::index_type; + auto [__mapping, __offset] = __mdspan::__submapping( + __md.mapping(), __mdspan::__slice_cast<_IndexType>(__raw_slices)...); + return std::mdspan( + __md.accessor().offset(__md.data_handle(), __offset), + std::move(__mapping), + typename _Accessor::offset_policy(__md.accessor())); + } #endif // __glibcxx_submdspan _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 7c157ea..3f0bcc4e 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -826,7 +826,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Check if a type is one of the signed integer types. __extension__ template<typename _Tp> - using __is_signed_integer = __is_one_of<__remove_cv_t<_Tp>, + using __is_signed_integer = __is_one_of<_Tp, signed char, signed short, signed int, signed long, signed long long #if defined(__GLIBCXX_TYPE_INT_N_0) @@ -841,12 +841,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if defined(__GLIBCXX_TYPE_INT_N_3) , signed __GLIBCXX_TYPE_INT_N_3 #endif +#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__ + , signed __int128 +#endif >; // Check if a type is one of the unsigned integer types. __extension__ template<typename _Tp> - using __is_unsigned_integer = __is_one_of<__remove_cv_t<_Tp>, + using __is_unsigned_integer = __is_one_of<_Tp, unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long #if defined(__GLIBCXX_TYPE_INT_N_0) @@ -861,11 +864,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if defined(__GLIBCXX_TYPE_INT_N_3) , unsigned __GLIBCXX_TYPE_INT_N_3 #endif +#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__ + , unsigned __int128 +#endif >; // Check if a type is one of the signed or unsigned integer types. + // i.e. an integral type except bool, char, wchar_t, and charN_t. template<typename _Tp> - using __is_standard_integer + using __is_signed_or_unsigned_integer = __or_<__is_signed_integer<_Tp>, __is_unsigned_integer<_Tp>>; // __void_t (std::void_t for C++11) diff --git a/libstdc++-v3/include/std/utility b/libstdc++-v3/include/std/utility index 3ae1852..0f6dd82 100644 --- a/libstdc++-v3/include/std/utility +++ b/libstdc++-v3/include/std/utility @@ -78,7 +78,7 @@ #include <bits/utility.h> #if __cplusplus >= 202002L -#include <ext/numeric_traits.h> // __is_standard_integer, __int_traits +#include <bits/intcmp.h> #endif #if __cplusplus > 202302L @@ -129,76 +129,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void as_const(const _Tp&&) = delete; #endif -#ifdef __cpp_lib_integer_comparison_functions // C++ >= 20 - template<typename _Tp, typename _Up> - constexpr bool - cmp_equal(_Tp __t, _Up __u) noexcept - { - static_assert(__is_standard_integer<_Tp>::value); - static_assert(__is_standard_integer<_Up>::value); - - if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) - return __t == __u; - else if constexpr (is_signed_v<_Tp>) - return __t >= 0 && make_unsigned_t<_Tp>(__t) == __u; - else - return __u >= 0 && __t == make_unsigned_t<_Up>(__u); - } - - template<typename _Tp, typename _Up> - constexpr bool - cmp_not_equal(_Tp __t, _Up __u) noexcept - { return !std::cmp_equal(__t, __u); } - - template<typename _Tp, typename _Up> - constexpr bool - cmp_less(_Tp __t, _Up __u) noexcept - { - static_assert(__is_standard_integer<_Tp>::value); - static_assert(__is_standard_integer<_Up>::value); - - if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) - return __t < __u; - else if constexpr (is_signed_v<_Tp>) - return __t < 0 || make_unsigned_t<_Tp>(__t) < __u; - else - return __u >= 0 && __t < make_unsigned_t<_Up>(__u); - } - - template<typename _Tp, typename _Up> - constexpr bool - cmp_greater(_Tp __t, _Up __u) noexcept - { return std::cmp_less(__u, __t); } - - template<typename _Tp, typename _Up> - constexpr bool - cmp_less_equal(_Tp __t, _Up __u) noexcept - { return !std::cmp_less(__u, __t); } - - template<typename _Tp, typename _Up> - constexpr bool - cmp_greater_equal(_Tp __t, _Up __u) noexcept - { return !std::cmp_less(__t, __u); } - - template<typename _Res, typename _Tp> - constexpr bool - in_range(_Tp __t) noexcept - { - static_assert(__is_standard_integer<_Res>::value); - static_assert(__is_standard_integer<_Tp>::value); - using __gnu_cxx::__int_traits; - - if constexpr (is_signed_v<_Tp> == is_signed_v<_Res>) - return __int_traits<_Res>::__min <= __t - && __t <= __int_traits<_Res>::__max; - else if constexpr (is_signed_v<_Tp>) - return __t >= 0 - && make_unsigned_t<_Tp>(__t) <= __int_traits<_Res>::__max; - else - return __t <= make_unsigned_t<_Res>(__int_traits<_Res>::__max); - } -#endif // __cpp_lib_integer_comparison_functions - #ifdef __cpp_lib_to_underlying // C++ >= 23 /// Convert an object of enumeration type to its underlying type. template<typename _Tp> diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant index 2f44f97..f2f5583 100644 --- a/libstdc++-v3/include/std/variant +++ b/libstdc++-v3/include/std/variant @@ -393,8 +393,29 @@ namespace __variant _Variadic_union(in_place_index_t<_Np>, _Args&&...) = delete; }; - template<bool __trivially_destructible, typename _First, typename... _Rest> - union _Variadic_union<__trivially_destructible, _First, _Rest...> + template<typename _First, typename... _Rest> + union _Variadic_union<true, _First, _Rest...> + { + constexpr _Variadic_union() : _M_rest() { } + + template<typename... _Args> + constexpr + _Variadic_union(in_place_index_t<0>, _Args&&... __args) + : _M_first(in_place_index<0>, std::forward<_Args>(__args)...) + { } + + template<size_t _Np, typename... _Args> + constexpr + _Variadic_union(in_place_index_t<_Np>, _Args&&... __args) + : _M_rest(in_place_index<_Np-1>, std::forward<_Args>(__args)...) + { } + + _Uninitialized<_First> _M_first; + _Variadic_union<true, _Rest...> _M_rest; + }; + + template<typename _First, typename... _Rest> + union _Variadic_union<false, _First, _Rest...> { constexpr _Variadic_union() : _M_rest() { } @@ -410,24 +431,19 @@ namespace __variant : _M_rest(in_place_index<_Np-1>, std::forward<_Args>(__args)...) { } -#if __cpp_lib_variant >= 202106L _Variadic_union(const _Variadic_union&) = default; _Variadic_union(_Variadic_union&&) = default; _Variadic_union& operator=(const _Variadic_union&) = default; _Variadic_union& operator=(_Variadic_union&&) = default; - ~_Variadic_union() = default; - // If any alternative type is not trivially destructible then we need a // user-provided destructor that does nothing. The active alternative // will be destroyed by _Variant_storage::_M_reset() instead of here. - constexpr ~_Variadic_union() - requires (!__trivially_destructible) + _GLIBCXX20_CONSTEXPR ~_Variadic_union() { } -#endif _Uninitialized<_First> _M_first; - _Variadic_union<__trivially_destructible, _Rest...> _M_rest; + _Variadic_union<(is_trivially_destructible_v<_Rest> && ...), _Rest...> _M_rest; }; // _Never_valueless_alt is true for variant alternatives that can |
