Created on 2025-06-02.00:00:00 last changed 1 month ago
Proposed resolution:
This wording is relative to N5008.
[Drafting note: As drive-by fixes the edits for layout_left_padded<>::mapping and layout_right_padded<>::mapping also correct an editorial asymmetry between class header synopsis declaration form and prototype specification form of the corresponding constructors and adjust to the correct formatting of the exposition-only data member rank_.]
Modify [mdspan.layout.left.overview] as indicated:
namespace std {
template<class Extents>
class layout_left::mapping {
[…]
// [mdspan.layout.left.cons], constructors
[…]
template<class OtherExtents>
constexpr explicit(extents_type::rank() > 0see below)
mapping(const layout_stride::mapping<OtherExtents>&);
constexpr mapping& operator=(const mapping&) noexcept = default;
[…]
};
}
Modify [mdspan.layout.left.cons] as indicated:
template<class OtherExtents> constexpr explicit(extents_type::rank() > 0see below) mapping(const layout_stride::mapping<OtherExtents>& other);-13- Constraints: […]
-14- Preconditions: […] -15- Effects: […] -?- Remarks: The expression inside `explicit` is equivalent to:!(extents_type::rank() == 0 && is_convertible_v<OtherExtents, extents_type>)
Modify [mdspan.layout.right.overview] as indicated:
namespace std {
template<class Extents>
class layout_right::mapping {
[…]
// [mdspan.layout.right.cons], constructors
[…]
template<class OtherExtents>
constexpr explicit(extents_type::rank() > 0see below)
mapping(const layout_stride::mapping<OtherExtents>&);
constexpr mapping& operator=(const mapping&) noexcept = default;
[…]
};
}
Modify [mdspan.layout.right.cons] as indicated:
template<class OtherExtents> constexpr explicit(extents_type::rank() > 0see below) mapping(const layout_stride::mapping<OtherExtents>& other);-13- Constraints: […]
-14- Preconditions: […] -15- Effects: […] -?- Remarks: The expression inside `explicit` is equivalent to:!(extents_type::rank() == 0 && is_convertible_v<OtherExtents, extents_type>)
Modify [mdspan.layout.leftpad.overview] as indicated:
namespace std {
template<size_t PaddingValue>
template<class Extents>
class layout_left_padded<PaddingValue>::mapping {
[…]
// [mdspan.layout.leftpad.cons], constructors
[…]
template<class OtherExtents>
constexpr explicit(extents_type::rank() > 0see below)
mapping(const layout_stride::mapping<OtherExtents>&);
[…]
};
}
Modify [mdspan.layout.leftpad.cons] as indicated:
template<class OtherExtents> constexpr explicit(rank_ > 0see below) mapping(const layout_stride::mapping<OtherExtents>& other);-10- Constraints: […]
-11- Preconditions: […] -12- Effects: […] -?- Remarks: The expression inside `explicit` is equivalent to:!(rank_ == 0 && is_convertible_v<OtherExtents, extents_type>)template<class LayoutLeftPaddedMapping> constexpr explicit(see below) mapping(const LayoutLeftPaddedMapping& other);-13- Constraints: […]
[…] -16- Remarks: The expression inside `explicit` is equivalent to:!is_convertible_v<typename LayoutLeftPaddedMapping::extents_type, extents_type> || rank_> 1 && (padding_value != dynamic_extent || LayoutLeftPaddedMapping::padding_value == dynamic_extent)
Modify [mdspan.layout.rightpad.overview] as indicated:
namespace std {
template<size_t PaddingValue>
template<class Extents>
class layout_right_padded<PaddingValue>::mapping {
[…]
// [mdspan.layout.rightpad.cons], constructors
[…]
template<class OtherExtents>
constexpr explicit(rank_ > 0see below)
mapping(const layout_stride::mapping<OtherExtents>&);
[…]
};
}
Modify [mdspan.layout.rightpad.cons] as indicated:
template<class OtherExtents> constexpr explicit(rank_ > 0see below) mapping(const layout_stride::mapping<OtherExtents>& other);-10- Constraints: […]
-11- Preconditions: […] -12- Effects: […] -?- Remarks: The expression inside `explicit` is equivalent to:!(rank_ == 0 && is_convertible_v<OtherExtents, extents_type>)template<class LayoutRightPaddedMapping> constexpr explicit(see below) mapping(const LayoutRightPaddedMapping& other);-13- Constraints: […]
[…] -17- Remarks: The expression inside `explicit` is equivalent to:!is_convertible_v<typename LayoutRightPaddedMapping::extents_type, extents_type> || rank_ > 1 && (padding_value != dynamic_extent || LayoutRightPaddedMapping::padding_value == dynamic_extent)
[ Kona 2025-11-08; Status changed: Immediate → WP. ]
[ Kona 2025-11-05; approved by LWG. Status changed: New → Immediate. ]
[ 2025-09-27, Tomasz Kamiński fixes constraints in constructors from padded layouts ]
[ 2025-06-20, Luc Grosheintz provides further wording improvements ]
This wording is relative to N5008.
[Drafting note: As drive-by fixes the edits for layout_left_padded<>::mapping and layout_right_padded<>::mapping also correct an editorial asymmetry between class header synopsis declaration form and prototype specification form of the corresponding constructors and adjust to the correct formatting of the exposition-only data member rank_.]
Modify [mdspan.layout.left.overview] as indicated:
namespace std {
template<class Extents>
class layout_left::mapping {
[…]
// [mdspan.layout.left.cons], constructors
[…]
template<class OtherExtents>
constexpr explicit(extents_type::rank() > 0see below)
mapping(const layout_stride::mapping<OtherExtents>&);
constexpr mapping& operator=(const mapping&) noexcept = default;
[…]
};
}
Modify [mdspan.layout.left.cons] as indicated:
template<class OtherExtents> constexpr explicit(extents_type::rank() > 0see below) mapping(const layout_stride::mapping<OtherExtents>& other);-13- Constraints: […]
-14- Preconditions: […] -15- Effects: […] -?- Remarks: The expression inside `explicit` is equivalent to:!(extents_type::rank() == 0 && is_convertible_v<OtherExtents, extents_type>)
Modify [mdspan.layout.right.overview] as indicated:
namespace std {
template<class Extents>
class layout_right::mapping {
[…]
// [mdspan.layout.right.cons], constructors
[…]
template<class OtherExtents>
constexpr explicit(extents_type::rank() > 0see below)
mapping(const layout_stride::mapping<OtherExtents>&);
constexpr mapping& operator=(const mapping&) noexcept = default;
[…]
};
}
Modify [mdspan.layout.right.cons] as indicated:
template<class OtherExtents> constexpr explicit(extents_type::rank() > 0see below) mapping(const layout_stride::mapping<OtherExtents>& other);-13- Constraints: […]
-14- Preconditions: […] -15- Effects: […] -?- Remarks: The expression inside `explicit` is equivalent to:!(extents_type::rank() == 0 && is_convertible_v<OtherExtents, extents_type>)
Modify [mdspan.layout.leftpad.overview] as indicated:
namespace std {
template<size_t PaddingValue>
template<class Extents>
class layout_left_padded<PaddingValue>::mapping {
[…]
// [mdspan.layout.leftpad.cons], constructors
[…]
template<class OtherExtents>
constexpr explicit(extents_type::rank() > 0see below)
mapping(const layout_stride::mapping<OtherExtents>&);
[…]
};
}
Modify [mdspan.layout.leftpad.cons] as indicated:
template<class OtherExtents> constexpr explicit(rank_ > 0see below) mapping(const layout_stride::mapping<OtherExtents>& other);-10- Constraints: […]
-11- Preconditions: […] -12- Effects: […] -?- Remarks: The expression inside `explicit` is equivalent to:!(rank_ == 0 && is_convertible_v<OtherExtents, extents_type>)template<class LayoutLeftPaddedMapping> constexpr explicit(see below) mapping(const LayoutLeftPaddedMapping& other);-13- Constraints: […]
[…] -16- Remarks: The expression inside `explicit` is equivalent to:!is_convertible_v<typename LayoutLeftPaddedMapping::extents_type, extents_type> && rank_> 1 && (padding_value != dynamic_extent || LayoutLeftPaddedMapping::padding_value == dynamic_extent)
Modify [mdspan.layout.rightpad.overview] as indicated:
namespace std {
template<size_t PaddingValue>
template<class Extents>
class layout_right_padded<PaddingValue>::mapping {
[…]
// [mdspan.layout.rightpad.cons], constructors
[…]
template<class OtherExtents>
constexpr explicit(rank_ > 0see below)
mapping(const layout_stride::mapping<OtherExtents>&);
[…]
};
}
Modify [mdspan.layout.rightpad.cons] as indicated:
template<class OtherExtents> constexpr explicit(rank_ > 0see below) mapping(const layout_stride::mapping<OtherExtents>& other);-10- Constraints: […]
-11- Preconditions: […] -12- Effects: […] -?- Remarks: The expression inside `explicit` is equivalent to:!(rank_ == 0 && is_convertible_v<OtherExtents, extents_type>)template<class LayoutRightPaddedMapping> constexpr explicit(see below) mapping(const LayoutRightPaddedMapping& other);-13- Constraints: […]
[…] -17- Remarks: The expression inside `explicit` is equivalent to:!is_convertible_v<typename LayoutRightPaddedMapping::extents_type, extents_type> && rank_ > 1 && (padding_value != dynamic_extent || LayoutRightPaddedMapping::padding_value == dynamic_extent)
[ 2025-06-12; Reflector poll ]
Set priority to 2 after reflector poll.
This wording is relative to N5008.
[Drafting note: As drive-by fixes the edits for layout_left_padded<>::mapping and layout_right_padded<>::mapping also correct an editorial asymmetry between class header synopsis declaration form and prototype specification form of the corresponding constructors and adjust to the correct formatting of the exposition-only data member rank_.]
Modify [mdspan.layout.left.overview] as indicated:
namespace std {
template<class Extents>
class layout_left::mapping {
[…]
// [mdspan.layout.left.cons], constructors
[…]
template<class OtherExtents>
constexpr explicit(extents_type::rank() > 0see below)
mapping(const layout_stride::mapping<OtherExtents>&);
constexpr mapping& operator=(const mapping&) noexcept = default;
[…]
};
}
Modify [mdspan.layout.left.cons] as indicated:
template<class OtherExtents> constexpr explicit(extents_type::rank() > 0see below) mapping(const layout_stride::mapping<OtherExtents>& other);-13- Constraints: […]
-14- Preconditions: […] -15- Effects: […] -?- Remarks: The expression inside `explicit` is equivalent to:!(extents_type::rank() == 0 && is_convertible_v<OtherExtents, extents_type>)
Modify [mdspan.layout.right.overview] as indicated:
namespace std {
template<class Extents>
class layout_right::mapping {
[…]
// [mdspan.layout.right.cons], constructors
[…]
template<class OtherExtents>
constexpr explicit(extents_type::rank() > 0see below)
mapping(const layout_stride::mapping<OtherExtents>&);
constexpr mapping& operator=(const mapping&) noexcept = default;
[…]
};
}
Modify [mdspan.layout.right.cons] as indicated:
template<class OtherExtents> constexpr explicit(extents_type::rank() > 0see below) mapping(const layout_stride::mapping<OtherExtents>& other);-13- Constraints: […]
-14- Preconditions: […] -15- Effects: […] -?- Remarks: The expression inside `explicit` is equivalent to:!(extents_type::rank() == 0 && is_convertible_v<OtherExtents, extents_type>)
Modify [mdspan.layout.leftpad.overview] as indicated:
namespace std {
template<size_t PaddingValue>
template<class Extents>
class layout_left_padded<PaddingValue>::mapping {
[…]
// [mdspan.layout.leftpad.cons], constructors
[…]
template<class OtherExtents>
constexpr explicit(extents_type::rank() > 0see below)
mapping(const layout_stride::mapping<OtherExtents>&);
[…]
};
}
Modify [mdspan.layout.leftpad.cons] as indicated:
template<class OtherExtents> constexpr explicit(rank_ > 0see below) mapping(const layout_stride::mapping<OtherExtents>& other);-10- Constraints: […]
-11- Preconditions: […] -12- Effects: […] -?- Remarks: The expression inside `explicit` is equivalent to:!(rank_ == 0 && is_convertible_v<OtherExtents, extents_type>)
Modify [mdspan.layout.rightpad.overview] as indicated:
namespace std {
template<size_t PaddingValue>
template<class Extents>
class layout_right_padded<PaddingValue>::mapping {
[…]
// [mdspan.layout.rightpad.cons], constructors
[…]
template<class OtherExtents>
constexpr explicit(rank_ > 0see below)
mapping(const layout_stride::mapping<OtherExtents>&);
[…]
};
}
Modify [mdspan.layout.rightpad.cons] as indicated:
template<class OtherExtents> constexpr explicit(rank_ > 0see below) mapping(const layout_stride::mapping<OtherExtents>& other);-10- Constraints: […]
-11- Preconditions: […] -12- Effects: […] -?- Remarks: The expression inside `explicit` is equivalent to:!(rank_ == 0 && is_convertible_v<OtherExtents, extents_type>)
Commonly, two layouts are considered convertible, if the underlying `extent_types` are convertible.
However, for the two ctors `layout_left::mapping(layout_stride::mapping)` and `layout_right::mapping(layout_stride::mapping)`, the condition is rank > 0. Therefore,
using E1 = std::extents<int>;
using E2 = std::extents<unsigned int>;
static_assert(std::is_convertible_v<
std::layout_stride::mapping<E2>,
std::layout_right::mapping<E1>
>);
even though:
static_assert(!std::is_convertible_v<E2, E1>);
Moreover, for rank 0 `layout_stride` can be converted to any specialization of `layout_left` or `layout_right`; but not to every specialization of `layout_stride`.
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2025-11-11 10:48:55 | admin | set | messages: + msg15668 |
| 2025-11-11 10:48:55 | admin | set | status: immediate -> wp |
| 2025-11-05 21:30:43 | admin | set | messages: + msg15533 |
| 2025-11-05 21:30:43 | admin | set | status: new -> immediate |
| 2025-08-29 17:48:54 | admin | set | messages: + msg14975 |
| 2025-06-28 12:53:59 | admin | set | messages: + msg14867 |
| 2025-06-12 20:53:08 | admin | set | messages: + msg14798 |
| 2025-06-06 17:05:10 | admin | set | messages: + msg14779 |
| 2025-06-02 00:00:00 | admin | create | |