[libcxx-commits] [libcxx] 7bdf416 - [libc++] Remove conditional noexcepts from view_interface.

Arthur O'Dwyer via libcxx-commits libcxx-commits at lists.llvm.org
Tue Feb 15 08:13:41 PST 2022


Author: Arthur O'Dwyer
Date: 2022-02-15T11:12:42-05:00
New Revision: 7bdf41653c90a6f1802e79b12b52d2d55cb9bd8d

URL: https://github.com/llvm/llvm-project/commit/7bdf41653c90a6f1802e79b12b52d2d55cb9bd8d
DIFF: https://github.com/llvm/llvm-project/commit/7bdf41653c90a6f1802e79b12b52d2d55cb9bd8d.diff

LOG: [libc++] Remove conditional noexcepts from view_interface.

As suggested in D117966.
These conditional noexcepts are *permitted* by the Standard (as long
as there were no mistakes in them, I guess); but not *mandated*.
The Standard doesn't put any noexcept-specifications on these member functions.
The same logic would apply to `transform_view::iterator::operator*`
and `transform_view::iterator::operator[]`, but the Standard mandates
conditional noexcept on `iter_move(transform_view::iterator)`, and
I think it doesn't make much sense to say "moving from this iterator
is conditionally noexcept but not-moving from it is noexcept(false),"
so I'm leaving transform_view alone for now.

Differential Revision: https://reviews.llvm.org/D119374

Added: 
    

Modified: 
    libcxx/include/__ranges/view_interface.h
    libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__ranges/view_interface.h b/libcxx/include/__ranges/view_interface.h
index 190bb8ad9cfdd..b0794b02b963b 100644
--- a/libcxx/include/__ranges/view_interface.h
+++ b/libcxx/include/__ranges/view_interface.h
@@ -9,6 +9,8 @@
 #ifndef _LIBCPP___RANGES_VIEW_INTERFACE_H
 #define _LIBCPP___RANGES_VIEW_INTERFACE_H
 
+#include <__concepts/derived_from.h>
+#include <__concepts/same_as.h>
 #include <__config>
 #include <__debug>
 #include <__iterator/concepts.h>
@@ -18,7 +20,6 @@
 #include <__ranges/access.h>
 #include <__ranges/concepts.h>
 #include <__ranges/empty.h>
-#include <concepts>
 #include <type_traits>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -31,12 +32,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 namespace ranges {
 
-template<class _Tp>
-concept __can_empty = requires(_Tp __t) { ranges::empty(__t); };
-
-template<class _Tp>
-void __implicitly_convert_to(type_identity_t<_Tp>) noexcept;
-
 template<class _Derived>
   requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>>
 class view_interface {
@@ -55,7 +50,6 @@ class view_interface {
 public:
   template<class _D2 = _Derived>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty()
-    noexcept(noexcept(__implicitly_convert_to<bool>(ranges::begin(__derived()) == ranges::end(__derived()))))
     requires forward_range<_D2>
   {
     return ranges::begin(__derived()) == ranges::end(__derived());
@@ -63,7 +57,6 @@ class view_interface {
 
   template<class _D2 = _Derived>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const
-    noexcept(noexcept(__implicitly_convert_to<bool>(ranges::begin(__derived()) == ranges::end(__derived()))))
     requires forward_range<const _D2>
   {
     return ranges::begin(__derived()) == ranges::end(__derived());
@@ -72,8 +65,7 @@ class view_interface {
   template<class _D2 = _Derived>
   _LIBCPP_HIDE_FROM_ABI
   constexpr explicit operator bool()
-    noexcept(noexcept(ranges::empty(declval<_D2>())))
-    requires __can_empty<_D2>
+    requires requires (_D2& __t) { ranges::empty(__t); }
   {
     return !ranges::empty(__derived());
   }
@@ -81,8 +73,7 @@ class view_interface {
   template<class _D2 = _Derived>
   _LIBCPP_HIDE_FROM_ABI
   constexpr explicit operator bool() const
-    noexcept(noexcept(ranges::empty(declval<const _D2>())))
-    requires __can_empty<const _D2>
+    requires requires (const _D2& __t) { ranges::empty(__t); }
   {
     return !ranges::empty(__derived());
   }
@@ -90,7 +81,6 @@ class view_interface {
   template<class _D2 = _Derived>
   _LIBCPP_HIDE_FROM_ABI
   constexpr auto data()
-    noexcept(noexcept(std::to_address(ranges::begin(__derived()))))
     requires contiguous_iterator<iterator_t<_D2>>
   {
     return std::to_address(ranges::begin(__derived()));
@@ -99,7 +89,6 @@ class view_interface {
   template<class _D2 = _Derived>
   _LIBCPP_HIDE_FROM_ABI
   constexpr auto data() const
-    noexcept(noexcept(std::to_address(ranges::begin(__derived()))))
     requires range<const _D2> && contiguous_iterator<iterator_t<const _D2>>
   {
     return std::to_address(ranges::begin(__derived()));
@@ -108,9 +97,7 @@ class view_interface {
   template<class _D2 = _Derived>
   _LIBCPP_HIDE_FROM_ABI
   constexpr auto size()
-    noexcept(noexcept(ranges::end(__derived()) - ranges::begin(__derived())))
-    requires forward_range<_D2>
-      && sized_sentinel_for<sentinel_t<_D2>, iterator_t<_D2>>
+    requires forward_range<_D2> && sized_sentinel_for<sentinel_t<_D2>, iterator_t<_D2>>
   {
     return ranges::end(__derived()) - ranges::begin(__derived());
   }
@@ -118,9 +105,7 @@ class view_interface {
   template<class _D2 = _Derived>
   _LIBCPP_HIDE_FROM_ABI
   constexpr auto size() const
-    noexcept(noexcept(ranges::end(__derived()) - ranges::begin(__derived())))
-    requires forward_range<const _D2>
-      && sized_sentinel_for<sentinel_t<const _D2>, iterator_t<const _D2>>
+    requires forward_range<const _D2> && sized_sentinel_for<sentinel_t<const _D2>, iterator_t<const _D2>>
   {
     return ranges::end(__derived()) - ranges::begin(__derived());
   }
@@ -128,7 +113,6 @@ class view_interface {
   template<class _D2 = _Derived>
   _LIBCPP_HIDE_FROM_ABI
   constexpr decltype(auto) front()
-    noexcept(noexcept(*ranges::begin(__derived())))
     requires forward_range<_D2>
   {
     _LIBCPP_ASSERT(!empty(),
@@ -139,7 +123,6 @@ class view_interface {
   template<class _D2 = _Derived>
   _LIBCPP_HIDE_FROM_ABI
   constexpr decltype(auto) front() const
-    noexcept(noexcept(*ranges::begin(__derived())))
     requires forward_range<const _D2>
   {
     _LIBCPP_ASSERT(!empty(),
@@ -150,7 +133,6 @@ class view_interface {
   template<class _D2 = _Derived>
   _LIBCPP_HIDE_FROM_ABI
   constexpr decltype(auto) back()
-    noexcept(noexcept(*ranges::prev(ranges::end(__derived()))))
     requires bidirectional_range<_D2> && common_range<_D2>
   {
     _LIBCPP_ASSERT(!empty(),
@@ -161,7 +143,6 @@ class view_interface {
   template<class _D2 = _Derived>
   _LIBCPP_HIDE_FROM_ABI
   constexpr decltype(auto) back() const
-    noexcept(noexcept(*ranges::prev(ranges::end(__derived()))))
     requires bidirectional_range<const _D2> && common_range<const _D2>
   {
     _LIBCPP_ASSERT(!empty(),
@@ -172,7 +153,6 @@ class view_interface {
   template<random_access_range _RARange = _Derived>
   _LIBCPP_HIDE_FROM_ABI
   constexpr decltype(auto) operator[](range_
diff erence_t<_RARange> __index)
-    noexcept(noexcept(ranges::begin(__derived())[__index]))
   {
     return ranges::begin(__derived())[__index];
   }
@@ -180,7 +160,6 @@ class view_interface {
   template<random_access_range _RARange = const _Derived>
   _LIBCPP_HIDE_FROM_ABI
   constexpr decltype(auto) operator[](range_
diff erence_t<_RARange> __index) const
-    noexcept(noexcept(ranges::begin(__derived())[__index]))
   {
     return ranges::begin(__derived())[__index];
   }

diff  --git a/libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp b/libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp
index 2720a75e7b8da..9faa3f564f5b6 100644
--- a/libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp
+++ b/libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp
@@ -126,17 +126,16 @@ struct DataIsNull : std::ranges::view_interface<DataIsNull> {
 };
 static_assert(std::ranges::view<DataIsNull>);
 
-template<bool IsNoexcept>
-struct BoolConvertibleComparison : std::ranges::view_interface<BoolConvertibleComparison<IsNoexcept>> {
+struct BoolConvertibleComparison : std::ranges::view_interface<BoolConvertibleComparison> {
   struct ResultType {
     bool value;
-    constexpr operator bool() const noexcept(IsNoexcept) { return value; }
+    constexpr operator bool() const { return value; }
   };
 
   struct SentinelType {
     int *base_;
-    SentinelType() = default;
-    explicit constexpr SentinelType(int *base) : base_(base) {}
+    explicit SentinelType() = default;
+    constexpr explicit SentinelType(int *base) : base_(base) {}
     friend constexpr ResultType operator==(ForwardIter const& iter, SentinelType const& sent) noexcept { return {iter.base() == sent.base_}; }
     friend constexpr ResultType operator==(SentinelType const& sent, ForwardIter const& iter) noexcept { return {iter.base() == sent.base_}; }
     friend constexpr ResultType operator!=(ForwardIter const& iter, SentinelType const& sent) noexcept { return {iter.base() != sent.base_}; }
@@ -144,11 +143,10 @@ struct BoolConvertibleComparison : std::ranges::view_interface<BoolConvertibleCo
   };
 
   int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
-  constexpr ForwardIter begin() const noexcept { return ForwardIter(const_cast<int*>(buff)); }
-  constexpr SentinelType end() const noexcept { return SentinelType(const_cast<int*>(buff) + 8); }
+  constexpr ForwardIter begin() const { return ForwardIter(const_cast<int*>(buff)); }
+  constexpr SentinelType end() const { return SentinelType(const_cast<int*>(buff) + 8); }
 };
-static_assert(std::ranges::view<BoolConvertibleComparison<true>>);
-static_assert(std::ranges::view<BoolConvertibleComparison<false>>);
+static_assert(std::ranges::view<BoolConvertibleComparison>);
 
 template<class T>
 concept EmptyInvocable = requires (T const& obj) { obj.empty(); };
@@ -189,19 +187,17 @@ constexpr bool testEmpty() {
   MoveOnlyForwardRange moveOnly;
   assert(!std::move(moveOnly).empty());
 
-  BoolConvertibleComparison<true> boolConv;
-  BoolConvertibleComparison<false> boolConv2;
-  LIBCPP_ASSERT_NOEXCEPT(boolConv.empty());
-  ASSERT_NOT_NOEXCEPT(boolConv2.empty());
+  BoolConvertibleComparison boolConv;
+  ASSERT_NOT_NOEXCEPT(boolConv.empty());
 
   assert(!boolConv.empty());
-  assert(!static_cast<BoolConvertibleComparison<true> const&>(boolConv).empty());
+  assert(!static_cast<const BoolConvertibleComparison&>(boolConv).empty());
 
   assert(boolConv);
-  assert(static_cast<BoolConvertibleComparison<true> const&>(boolConv));
+  assert(static_cast<const BoolConvertibleComparison&>(boolConv));
 
   assert(!std::ranges::empty(boolConv));
-  assert(!std::ranges::empty(static_cast<BoolConvertibleComparison<true> const&>(boolConv)));
+  assert(!std::ranges::empty(static_cast<const BoolConvertibleComparison&>(boolConv)));
 
   return true;
 }


        


More information about the libcxx-commits mailing list