The changes needed for submdspan are:
* In submdspan related code the user-defined integer-like
types need to be copy- and move-constructable.
* The traits for writing tests that work with both left- and right,
possibly padded, layouts will also be useful for submdspan.
Therefore, this code is moved up and generalized.
* Move __offset further up in <mdspan> and fix some formatting
mistakes.
* include/std/mdspan: Improve formatting and placement.
* testsuite/23_containers/mdspan/int_like.h: Optionally,
add move- and copy-ctors.
* testsuite/23_containers/mdspan/layouts/padded_traits.h: Move to...
* testsuite/23_containers/mdspan/layout_traits.h: ...here.
* testsuite/23_containers/mdspan/layouts/ctors.cc: Fix include.
* testsuite/23_containers/mdspan/layouts/mapping.cc: Ditto.
* testsuite/23_containers/mdspan/layouts/padded.cc: Ditto.
* testsuite/23_containers/mdspan/layouts/padded_neg.cc: Ditto.
Signed-off-by: Luc Grosheintz <[email protected]>
---
libstdc++-v3/include/std/mdspan | 52 ++++++++-------
.../testsuite/23_containers/mdspan/int_like.h | 25 ++++---
.../padded_traits.h => layout_traits.h} | 65 +++++++++++++++----
.../23_containers/mdspan/layouts/ctors.cc | 2 +-
.../23_containers/mdspan/layouts/mapping.cc | 2 +-
.../23_containers/mdspan/layouts/padded.cc | 2 +-
.../mdspan/layouts/padded_neg.cc | 2 +-
7 files changed, 103 insertions(+), 47 deletions(-)
rename libstdc++-v3/testsuite/23_containers/mdspan/{layouts/padded_traits.h =>
layout_traits.h} (70%)
diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan
index bd7a2a201a7..0a49f24fd3f 100644
--- a/libstdc++-v3/include/std/mdspan
+++ b/libstdc++-v3/include/std/mdspan
@@ -338,21 +338,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __glibcxx_submdspan
struct full_extent_t
{
explicit full_extent_t() = default;
};
inline constexpr full_extent_t full_extent{};
template<typename _OffsetType, typename _ExtentType, typename _StrideType>
- struct strided_slice {
+ struct strided_slice
+ {
static_assert(__is_standard_integer<_OffsetType>::value
|| __detail::__integral_constant_like<_OffsetType>);
static_assert(__is_standard_integer<_ExtentType>::value
|| __detail::__integral_constant_like<_ExtentType>);
static_assert(__is_standard_integer<_StrideType>::value
|| __detail::__integral_constant_like<_StrideType>);
using offset_type = _OffsetType;
using extent_type = _ExtentType;
using stride_type = _StrideType;
@@ -361,21 +362,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
[[no_unique_address]] extent_type extent{};
[[no_unique_address]] stride_type stride{};
};
template<typename _Mapping>
struct submdspan_mapping_result
{
[[no_unique_address]] _Mapping mapping = _Mapping();
size_t offset{};
};
-#endif
+#endif // __glibcxx_submdspan
template<typename _IndexType, size_t... _Extents>
class extents
{
static_assert(__is_standard_integer<_IndexType>::value,
"IndexType must be a signed or unsigned integer type");
static_assert(
(__mdspan::__valid_static_extent<_Extents, _IndexType> && ...),
"Extents must either be dynamic or representable as IndexType");
@@ -546,21 +547,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__ret *= size_t(__factor);
return static_cast<typename _Extents::index_type>(__ret);
}
// Preconditions: _r < _Extents::rank()
template<typename _Extents>
constexpr typename _Extents::index_type
__fwd_prod(const _Extents& __exts, size_t __begin, size_t __end) noexcept
{
size_t __sta_prod = [__begin, __end] {
- span<const size_t> __sta_exts = __static_extents<_Extents>(__begin,
__end);
+ span<const size_t> __sta_exts
+ = __static_extents<_Extents>(__begin, __end);
size_t __ret = 1;
for(auto __ext : __sta_exts)
if (__ext != dynamic_extent)
__ret *= __ext;
return __ret;
}();
return __extents_prod(__exts, __sta_prod, __begin, __end);
}
template<typename _Extents>
@@ -762,21 +764,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
}
template<typename _Extents, typename _IndexType>
concept __representable_size = _Extents::rank_dynamic() != 0
|| __contains_zero(__static_extents<_Extents>())
|| (__static_quotient<_Extents, _IndexType>() != 0);
template<typename _Layout, typename _Mapping>
concept __mapping_of =
- is_same_v<typename _Layout::template mapping<typename
_Mapping::extents_type>,
+ is_same_v<typename _Layout::template mapping<
+ typename _Mapping::extents_type>,
_Mapping>;
template<template<size_t> typename _Layout, typename _Mapping>
concept __padded_mapping_of = __mapping_of<
_Layout<_Mapping::padding_value>, _Mapping>;
#ifdef __glibcxx_padded_layouts
template<typename _Mapping>
constexpr bool __is_left_padded_mapping = __padded_mapping_of<
layout_left_padded, _Mapping>;
@@ -797,20 +800,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|| __mapping_of<layout_stride, _Mapping>
#ifdef __glibcxx_padded_layouts
|| __is_left_padded_mapping<_Mapping>
|| __is_right_padded_mapping<_Mapping>
#endif
;
// A tag type to create internal ctors.
class __internal_ctor
{ };
+
+ template<typename _Mapping>
+ constexpr typename _Mapping::index_type
+ __offset(const _Mapping& __m) noexcept
+ {
+ using _IndexType = typename _Mapping::index_type;
+ constexpr auto __rank = _Mapping::extents_type::rank();
+
+ if constexpr (__standardized_mapping<_Mapping>)
+ return 0;
+ else if (__empty(__m.extents()))
+ return 0;
+ else
+ {
+ auto __impl = [&__m]<size_t... _Counts>(index_sequence<_Counts...>)
+ { return __m(((void) _Counts, _IndexType(0))...); };
+ return __impl(make_index_sequence<__rank>());
+ }
+ }
}
template<typename _Extents>
class layout_left::mapping
{
public:
using extents_type = _Extents;
using index_type = typename extents_type::index_type;
using size_type = typename extents_type::size_type;
using rank_type = typename extents_type::rank_type;
@@ -1030,21 +1052,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
extents_type>)
mapping(const _RightPaddedMapping& __other) noexcept
: mapping(__other.extents(), __mdspan::__internal_ctor{})
{
constexpr size_t __rank = extents_type::rank();
constexpr size_t __ostride_sta
= __mdspan::__get_static_stride<_RightPaddedMapping>();
if constexpr (__rank > 1)
{
- if constexpr (extents_type::static_extent(__rank - 1) !=
dynamic_extent
+ if constexpr (
+ extents_type::static_extent(__rank - 1) != dynamic_extent
&& __ostride_sta != dynamic_extent)
static_assert(extents_type::static_extent(__rank - 1)
== __ostride_sta);
else
__glibcxx_assert(__other.stride(__rank - 2)
== __other.extents().extent(__rank - 1));
}
}
#endif
@@ -1129,39 +1152,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
requires __is_extents<typename _Mp::extents_type>;
{ _Mp::is_always_strided() } -> same_as<bool>;
{ _Mp::is_always_exhaustive() } -> same_as<bool>;
{ _Mp::is_always_unique() } -> same_as<bool>;
bool_constant<_Mp::is_always_strided()>::value;
bool_constant<_Mp::is_always_exhaustive()>::value;
bool_constant<_Mp::is_always_unique()>::value;
};
- template<typename _Mapping>
- constexpr typename _Mapping::index_type
- __offset(const _Mapping& __m) noexcept
- {
- using _IndexType = typename _Mapping::index_type;
- constexpr auto __rank = _Mapping::extents_type::rank();
-
- if constexpr (__standardized_mapping<_Mapping>)
- return 0;
- else if (__empty(__m.extents()))
- return 0;
- else
- {
- auto __impl = [&__m]<size_t... _Counts>(index_sequence<_Counts...>)
- { return __m(((void) _Counts, _IndexType(0))...); };
- return __impl(make_index_sequence<__rank>());
- }
- }
-
template<typename _Mapping, typename... _Indices>
constexpr typename _Mapping::index_type
__linear_index_strides(const _Mapping& __m, _Indices... __indices)
noexcept
{
using _IndexType = typename _Mapping::index_type;
_IndexType __res = 0;
if constexpr (sizeof...(__indices) > 0)
{
auto __update = [&, __pos = 0u](_IndexType __idx) mutable
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/int_like.h
b/libstdc++-v3/testsuite/23_containers/mdspan/int_like.h
index e9172c13455..2f79b9dd3b5 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/int_like.h
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/int_like.h
@@ -2,38 +2,47 @@
#define TEST_MDSPAN_INT_LIKE_H
enum class CustomIndexKind
{
Const,
Throwing,
Mutating,
RValue,
};
-template<CustomIndexKind Kind>
+template<CustomIndexKind Kind, bool Copyable = false>
class CustomIndexType
{
public:
explicit
CustomIndexType(int i)
: value(i)
{ }
- CustomIndexType() = delete;
- CustomIndexType(const CustomIndexType&) = delete;
- CustomIndexType(CustomIndexType&&) = delete;
+ CustomIndexType() requires(Copyable) = default;
+ CustomIndexType() requires(!Copyable) = delete;
- const CustomIndexType&
- operator=(const CustomIndexType&) = delete;
+ CustomIndexType(const CustomIndexType&) requires(Copyable) = default;
+ CustomIndexType(const CustomIndexType&) requires(!Copyable) = delete;
- const CustomIndexType&
- operator=(CustomIndexType&&) = delete;
+ CustomIndexType(CustomIndexType&&) requires(Copyable) = default;
+ CustomIndexType(CustomIndexType&&) requires(!Copyable) = delete;
+
+ CustomIndexType&
+ operator=(const CustomIndexType&) requires(Copyable) = default;
+ CustomIndexType&
+ operator=(const CustomIndexType&) requires(!Copyable) = delete;
+
+ CustomIndexType&
+ operator=(CustomIndexType&&) requires(Copyable) = default;
+ CustomIndexType&
+ operator=(CustomIndexType&&) requires(!Copyable) = delete;
constexpr
operator int() const noexcept
requires (Kind == CustomIndexKind::Const)
{ return value; }
constexpr
operator int() const
requires (Kind == CustomIndexKind::Throwing)
{ return value; }
diff --git
a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded_traits.h
b/libstdc++-v3/testsuite/23_containers/mdspan/layout_traits.h
similarity index 70%
rename from libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded_traits.h
rename to libstdc++-v3/testsuite/23_containers/mdspan/layout_traits.h
index 788ae82fcc4..619cab53b9e 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded_traits.h
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/layout_traits.h
@@ -1,15 +1,21 @@
-#ifndef TEST_MDSPAN_PADDED_TRAITS_H
-#define TEST_MDSPAN_PADDED_TRAITS_H
+#ifndef TEST_MDSPAN_LAYOUT_TRAITS_H
+#define TEST_MDSPAN_LAYOUT_TRAITS_H
#include <algorithm>
+enum class PaddingSide
+{
+ Left,
+ Right
+};
+
template<typename Layout>
constexpr static bool is_left_padded = false;
#if __cplusplus > 202302L
template<size_t PaddingValue>
constexpr static bool is_left_padded<std::layout_left_padded<PaddingValue>>
= true;
#endif
template<typename Layout>
@@ -19,53 +25,61 @@ template<typename Layout>
template<size_t PaddingValue>
constexpr static bool is_right_padded<std::layout_right_padded<PaddingValue>>
= true;
#endif
template<typename Layout>
constexpr bool
is_padded_layout = is_left_padded<Layout> || is_right_padded<Layout>;
#if __cplusplus > 202302L
+template<PaddingSide Side, typename Layout>
+ constexpr bool
+ is_same_padded;
+
+template<typename Layout>
+ constexpr bool
+ is_same_padded<PaddingSide::Left, Layout> = is_left_padded<Layout>;
+
+template<typename Layout>
+ constexpr bool
+ is_same_padded<PaddingSide::Right, Layout> = is_right_padded<Layout>;
+
template<typename Extents>
constexpr auto
dynamic_extents_array(const Extents& exts)
{
std::array<typename Extents::index_type, Extents::rank()> ret;
for(size_t i = 0; i < Extents::rank(); ++i)
ret[i] = exts.extent(i);
return ret;
}
-enum class PaddingSide
-{
- Left,
- Right
-};
-
struct DeducePaddingSide
{
template<template<size_t> typename Layout>
constexpr static PaddingSide
from_template()
{
if constexpr (std::same_as<Layout<0>, std::layout_left_padded<0>>)
return PaddingSide::Left;
else
return PaddingSide::Right;
}
template<typename Layout>
constexpr static PaddingSide
from_typename()
{
- if constexpr (is_left_padded<Layout>)
+ if constexpr (std::same_as<Layout, std::layout_left>)
+ return PaddingSide::Left;
+ else if constexpr (is_left_padded<Layout>)
return PaddingSide::Left;
else
return PaddingSide::Right;
}
};
template<PaddingSide Side>
struct LayoutTraits;
template<>
@@ -77,22 +91,32 @@ template<>
template<typename Extents>
using extents_type = Extents;
template<typename Extents>
constexpr static extents_type<Extents>
make_extents(const Extents& exts)
{ return exts; }
template<typename T, size_t N>
constexpr static std::array<T, N>
- make_array(const std::array<T, N>& expected)
- { return expected; }
+ make_array(const std::array<T, N>& a)
+ { return a; }
+
+ template<typename... Indices>
+ constexpr static auto
+ make_indices(Indices... indices)
+ { return std::array{indices...}; }
+
+ template<typename... Ts>
+ constexpr static std::tuple<Ts...>
+ make_tuple(const std::tuple<Ts...>& tup)
+ { return tup; }
template<typename Mapping>
constexpr static auto
padded_stride(const Mapping& m)
{ return m.stride(1); }
template<typename Extents>
constexpr static auto
padded_extent(const Extents& exts)
{ return exts.extent(0); }
@@ -121,20 +145,39 @@ template<>
using extents_type = decltype(make_extents(std::declval<Extents>()));
template<typename T, size_t N>
constexpr static std::array<T, N>
make_array(std::array<T, N> a)
{
std::ranges::reverse(a);
return a;
}
+ template<typename... Indices>
+ constexpr static auto
+ make_indices(Indices... indices)
+ { return make_array(std::array{indices...}); }
+
+ template<typename... Ts>
+ constexpr static auto
+ make_tuple(const std::tuple<Ts...>& tup)
+ {
+ constexpr size_t rank = sizeof...(Ts);
+ auto impl = [&]<size_t... I>(std::index_sequence<I...>)
+ {
+ auto idx = [rank](size_t i) consteval
+ { return rank - 1 - i; };
+ return std::tuple<Ts...[idx(I)]...>{get<idx(I)>(tup)...};
+ };
+ return impl(std::make_index_sequence<rank>());
+ }
+
template<typename Mapping>
constexpr static auto
padded_stride(const Mapping& m)
{
auto rank = Mapping::extents_type::rank();
return m.stride(rank - 2);
}
template<typename Extents>
constexpr static auto
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc
b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc
index 27065a0dfc6..80ae5d8d56a 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc
@@ -1,14 +1,14 @@
// { dg-do run { target c++23 } }
#include <mdspan>
-#include "padded_traits.h"
+#include "../layout_traits.h"
#include <cstdint>
#include <testsuite_hooks.h>
constexpr size_t dyn = std::dynamic_extent;
template<typename Mapping, typename IndexType, size_t... Extents>
constexpr void
verify(std::extents<IndexType, Extents...> oexts)
{
auto m = Mapping(oexts);
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc
b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc
index d1486e4e11c..17cfac54113 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc
@@ -1,15 +1,15 @@
// { dg-do run { target c++23 } }
#include <mdspan>
#include "../int_like.h"
-#include "padded_traits.h"
+#include "../layout_traits.h"
#include <cstdint>
#include <testsuite_hooks.h>
constexpr size_t dyn = std::dynamic_extent;
template<typename Mapping>
concept has_static_is_exhaustive = requires
{
{ Mapping::is_exhaustive() } -> std::same_as<bool>;
};
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded.cc
b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded.cc
index cf4821a3c74..19fdf93ce0d 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded.cc
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded.cc
@@ -1,16 +1,16 @@
// { dg-do run { target c++26 } }
#include <mdspan>
#include <cstdint>
#include "../int_like.h"
-#include "padded_traits.h"
+#include "../layout_traits.h"
#include <testsuite_hooks.h>
constexpr size_t dyn = std::dynamic_extent;
template<template<size_t> typename Layout>
constexpr bool
test_representable_padded_size()
{
using Traits = LayoutTraits<DeducePaddingSide::from_template<Layout>()>;
{
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded_neg.cc
b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded_neg.cc
index a758f74287f..4073f683822 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/padded_neg.cc
@@ -1,14 +1,14 @@
// { dg-do compile { target c++26 } }
#include <mdspan>
-#include "padded_traits.h"
+#include "../layout_traits.h"
#include <cstdint>
constexpr size_t dyn = std::dynamic_extent;
template<template<size_t> typename Layout>
constexpr bool
test_from_extens_representable_sta()
{
using E1 = std::extents<uint8_t, 8, 128>;
auto m = typename Layout<dyn>::mapping(E1{}); // { dg-error "required
from" }
--
2.51.2