[libc++] LWG-4021 "mdspan::is_always_meow()
should be noexcept
", use LIBCPP_STATIC_ASSERT
for noexcept
strengthening (#74254)
Found while running libc++'s test suite with MSVC's STL. * I've filed [LWG-4021](https://cplusplus.github.io/LWG/issue4021) "`mdspan::is_always_meow()` should be `noexcept`" and implemented this in libc++'s product and test code. * Use `LIBCPP_STATIC_ASSERT` to avoid issues with `noexcept` strengthening in MSVC's STL. + As permitted by the Standard, MSVC's STL conditionally strengthens `mdspan` construction/`is_meow`/`stride` and `elements_view` iterator `base() &&`, and always strengthens `basic_stringbuf` `swap`. + In `mdspan/properties.pass.cpp`, this also upgrades runtime `assert`s to `static_assert`s. * Improvement: Upgrade `assert` to `static_assert` when inspecting the `noexcept`ness of `std::ranges::iter_move`. (These `!noexcept` tests weren't causing issues for MSVC's STL, so I didn't change them to be libc++-specific.)
This commit is contained in:
parent
78623b079b
commit
67c4033358
@ -244,9 +244,14 @@ public:
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr const mapping_type& mapping() const noexcept { return __map_; };
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr const accessor_type& accessor() const noexcept { return __acc_; };
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_unique() { return mapping_type::is_always_unique(); };
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_exhaustive() { return mapping_type::is_always_exhaustive(); };
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_strided() { return mapping_type::is_always_strided(); };
|
||||
// per LWG-4021 "mdspan::is_always_meow() should be noexcept"
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_unique() noexcept { return mapping_type::is_always_unique(); };
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_exhaustive() noexcept {
|
||||
return mapping_type::is_always_exhaustive();
|
||||
};
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_strided() noexcept {
|
||||
return mapping_type::is_always_strided();
|
||||
};
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool is_unique() const { return __map_.is_unique(); };
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool is_exhaustive() const { return __map_.is_exhaustive(); };
|
||||
|
@ -334,11 +334,12 @@ namespace std {
|
||||
constexpr const mapping_type& mapping() const noexcept { return map_; }
|
||||
constexpr const accessor_type& accessor() const noexcept { return acc_; }
|
||||
|
||||
static constexpr bool is_always_unique()
|
||||
// per LWG-4021 "mdspan::is_always_meow() should be noexcept"
|
||||
static constexpr bool is_always_unique() noexcept
|
||||
{ return mapping_type::is_always_unique(); }
|
||||
static constexpr bool is_always_exhaustive()
|
||||
static constexpr bool is_always_exhaustive() noexcept
|
||||
{ return mapping_type::is_always_exhaustive(); }
|
||||
static constexpr bool is_always_strided()
|
||||
static constexpr bool is_always_strided() noexcept
|
||||
{ return mapping_type::is_always_strided(); }
|
||||
|
||||
constexpr bool is_unique() const
|
||||
|
@ -65,7 +65,7 @@ test_mdspan_ctor_array(const H& handle, const M& map, const A&, std::array<typen
|
||||
}
|
||||
}
|
||||
|
||||
static_assert(!noexcept(MDS(handle, exts)));
|
||||
LIBCPP_STATIC_ASSERT(!noexcept(MDS(handle, exts)));
|
||||
|
||||
static_assert(check_mdspan_ctor_implicit<MDS, decltype(exts)> == (N == MDS::rank_dynamic()));
|
||||
|
||||
|
@ -51,7 +51,7 @@ constexpr void test_mdspan_types(const H& handle, const M& map, const A&) {
|
||||
assert((H::move_counter() == 1));
|
||||
}
|
||||
}
|
||||
static_assert(!noexcept(MDS(handle, map.extents())));
|
||||
LIBCPP_STATIC_ASSERT(!noexcept(MDS(handle, map.extents())));
|
||||
assert(m.extents() == map.extents());
|
||||
if constexpr (std::equality_comparable<H>)
|
||||
assert(m.data_handle() == handle);
|
||||
|
@ -48,7 +48,7 @@ constexpr void test_mdspan_types(const H& handle, const M& map, const A&) {
|
||||
assert((H::move_counter() == 1));
|
||||
}
|
||||
}
|
||||
static_assert(!noexcept(MDS(handle, map)));
|
||||
LIBCPP_STATIC_ASSERT(!noexcept(MDS(handle, map)));
|
||||
assert(m.extents() == map.extents());
|
||||
if constexpr (std::equality_comparable<H>)
|
||||
assert(m.data_handle() == handle);
|
||||
|
@ -43,7 +43,7 @@ constexpr void test_mdspan_types(const H& handle, const M& map, const A& acc) {
|
||||
assert((H::move_counter() == 1));
|
||||
}
|
||||
}
|
||||
static_assert(!noexcept(MDS(handle, map, acc)));
|
||||
LIBCPP_STATIC_ASSERT(!noexcept(MDS(handle, map, acc)));
|
||||
assert(m.extents() == map.extents());
|
||||
if constexpr (std::equality_comparable<H>)
|
||||
assert(m.data_handle() == handle);
|
||||
|
@ -65,7 +65,7 @@ test_mdspan_ctor_span(const H& handle, const M& map, const A&, std::span<typenam
|
||||
}
|
||||
}
|
||||
|
||||
static_assert(!noexcept(MDS(handle, exts)));
|
||||
LIBCPP_STATIC_ASSERT(!noexcept(MDS(handle, exts)));
|
||||
|
||||
static_assert(check_mdspan_ctor_implicit<MDS, decltype(exts)> == (N == MDS::rank_dynamic()));
|
||||
|
||||
|
@ -27,11 +27,12 @@
|
||||
// constexpr const data_handle_type& data_handle() const noexcept { return ptr_; }
|
||||
// constexpr const mapping_type& mapping() const noexcept { return map_; }
|
||||
// constexpr const accessor_type& accessor() const noexcept { return acc_; }
|
||||
// static constexpr bool is_always_unique()
|
||||
// /* per LWG-4021 "mdspan::is_always_meow() should be noexcept" */
|
||||
// static constexpr bool is_always_unique() noexcept
|
||||
// { return mapping_type::is_always_unique(); }
|
||||
// static constexpr bool is_always_exhaustive()
|
||||
// static constexpr bool is_always_exhaustive() noexcept
|
||||
// { return mapping_type::is_always_exhaustive(); }
|
||||
// static constexpr bool is_always_strided()
|
||||
// static constexpr bool is_always_strided() noexcept
|
||||
// { return mapping_type::is_always_strided(); }
|
||||
//
|
||||
// constexpr bool is_unique() const
|
||||
@ -141,15 +142,16 @@ constexpr void test_mdspan_types(const H& handle, const M& map, const A& acc) {
|
||||
ASSERT_SAME_TYPE(decltype(m.is_unique()), bool);
|
||||
ASSERT_SAME_TYPE(decltype(m.is_exhaustive()), bool);
|
||||
ASSERT_SAME_TYPE(decltype(m.is_strided()), bool);
|
||||
assert(!noexcept(MDS::is_always_unique()));
|
||||
assert(!noexcept(MDS::is_always_exhaustive()));
|
||||
assert(!noexcept(MDS::is_always_strided()));
|
||||
assert(!noexcept(m.is_unique()));
|
||||
assert(!noexcept(m.is_exhaustive()));
|
||||
assert(!noexcept(m.is_strided()));
|
||||
assert(MDS::is_always_unique() == M::is_always_unique());
|
||||
assert(MDS::is_always_exhaustive() == M::is_always_exhaustive());
|
||||
assert(MDS::is_always_strided() == M::is_always_strided());
|
||||
// per LWG-4021 "mdspan::is_always_meow() should be noexcept"
|
||||
static_assert(noexcept(MDS::is_always_unique()));
|
||||
static_assert(noexcept(MDS::is_always_exhaustive()));
|
||||
static_assert(noexcept(MDS::is_always_strided()));
|
||||
LIBCPP_STATIC_ASSERT(!noexcept(m.is_unique()));
|
||||
LIBCPP_STATIC_ASSERT(!noexcept(m.is_exhaustive()));
|
||||
LIBCPP_STATIC_ASSERT(!noexcept(m.is_strided()));
|
||||
static_assert(MDS::is_always_unique() == M::is_always_unique());
|
||||
static_assert(MDS::is_always_exhaustive() == M::is_always_exhaustive());
|
||||
static_assert(MDS::is_always_strided() == M::is_always_strided());
|
||||
assert(m.is_unique() == map.is_unique());
|
||||
assert(m.is_exhaustive() == map.is_exhaustive());
|
||||
assert(m.is_strided() == map.is_strided());
|
||||
@ -159,7 +161,7 @@ constexpr void test_mdspan_types(const H& handle, const M& map, const A& acc) {
|
||||
if (m.is_strided()) {
|
||||
for (typename MDS::rank_type r = 0; r < MDS::rank(); r++) {
|
||||
ASSERT_SAME_TYPE(decltype(m.stride(r)), typename MDS::index_type);
|
||||
assert(!noexcept(m.stride(r)));
|
||||
LIBCPP_STATIC_ASSERT(!noexcept(m.stride(r)));
|
||||
assert(m.stride(r) == map.stride(r));
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ static void test() {
|
||||
{
|
||||
std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_not_empty<CharT>> buf1;
|
||||
std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_not_empty<CharT>> buf;
|
||||
static_assert(!noexcept(buf.swap(buf1)));
|
||||
LIBCPP_STATIC_ASSERT(!noexcept(buf.swap(buf1)));
|
||||
}
|
||||
{
|
||||
std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_propagate_on_container_swap_not_empty<CharT>> buf1;
|
||||
|
@ -83,7 +83,7 @@ static void test() {
|
||||
{
|
||||
std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_not_empty<CharT>> buf1;
|
||||
std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_not_empty<CharT>> buf;
|
||||
static_assert(!noexcept(swap(buf, buf1)));
|
||||
LIBCPP_STATIC_ASSERT(!noexcept(swap(buf, buf1)));
|
||||
}
|
||||
{
|
||||
std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_propagate_on_container_swap_not_empty<CharT>> buf1;
|
||||
|
@ -158,15 +158,15 @@ constexpr bool test() {
|
||||
|
||||
auto unscoped = check_unqualified_lookup::unscoped_enum::a;
|
||||
assert(std::ranges::iter_move(unscoped) == check_unqualified_lookup::unscoped_enum::a);
|
||||
assert(!noexcept(std::ranges::iter_move(unscoped)));
|
||||
static_assert(!noexcept(std::ranges::iter_move(unscoped)));
|
||||
|
||||
auto scoped = check_unqualified_lookup::scoped_enum::a;
|
||||
assert(std::ranges::iter_move(scoped) == nullptr);
|
||||
assert(noexcept(std::ranges::iter_move(scoped)));
|
||||
static_assert(noexcept(std::ranges::iter_move(scoped)));
|
||||
|
||||
auto some_union = check_unqualified_lookup::some_union{0};
|
||||
assert(std::ranges::iter_move(some_union) == 0);
|
||||
assert(!noexcept(std::ranges::iter_move(some_union)));
|
||||
static_assert(!noexcept(std::ranges::iter_move(some_union)));
|
||||
|
||||
// Check noexcept-correctness
|
||||
static_assert(noexcept(std::ranges::iter_move(std::declval<WithADL<true>>())));
|
||||
|
@ -33,7 +33,7 @@ using ElementsIter = std::ranges::iterator_t<std::ranges::elements_view<BaseView
|
||||
static_assert(IsBaseNoexcept<const ElementsIter&>);
|
||||
static_assert(IsBaseNoexcept<ElementsIter&>);
|
||||
static_assert(IsBaseNoexcept<const ElementsIter&&>);
|
||||
static_assert(!IsBaseNoexcept<ElementsIter&&>);
|
||||
LIBCPP_STATIC_ASSERT(!IsBaseNoexcept<ElementsIter&&>);
|
||||
|
||||
constexpr bool test() {
|
||||
std::tuple<int> t{5};
|
||||
|
Loading…
x
Reference in New Issue
Block a user