Skip to content

Commit 7bdf416

Browse files
committed
[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
1 parent c9c9307 commit 7bdf416

File tree

2 files changed

+18
-43
lines changed

2 files changed

+18
-43
lines changed

libcxx/include/__ranges/view_interface.h

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#ifndef _LIBCPP___RANGES_VIEW_INTERFACE_H
1010
#define _LIBCPP___RANGES_VIEW_INTERFACE_H
1111

12+
#include <__concepts/derived_from.h>
13+
#include <__concepts/same_as.h>
1214
#include <__config>
1315
#include <__debug>
1416
#include <__iterator/concepts.h>
@@ -18,7 +20,6 @@
1820
#include <__ranges/access.h>
1921
#include <__ranges/concepts.h>
2022
#include <__ranges/empty.h>
21-
#include <concepts>
2223
#include <type_traits>
2324

2425
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -31,12 +32,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
3132

3233
namespace ranges {
3334

34-
template<class _Tp>
35-
concept __can_empty = requires(_Tp __t) { ranges::empty(__t); };
36-
37-
template<class _Tp>
38-
void __implicitly_convert_to(type_identity_t<_Tp>) noexcept;
39-
4035
template<class _Derived>
4136
requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>>
4237
class view_interface {
@@ -55,15 +50,13 @@ class view_interface {
5550
public:
5651
template<class _D2 = _Derived>
5752
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty()
58-
noexcept(noexcept(__implicitly_convert_to<bool>(ranges::begin(__derived()) == ranges::end(__derived()))))
5953
requires forward_range<_D2>
6054
{
6155
return ranges::begin(__derived()) == ranges::end(__derived());
6256
}
6357

6458
template<class _D2 = _Derived>
6559
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const
66-
noexcept(noexcept(__implicitly_convert_to<bool>(ranges::begin(__derived()) == ranges::end(__derived()))))
6760
requires forward_range<const _D2>
6861
{
6962
return ranges::begin(__derived()) == ranges::end(__derived());
@@ -72,25 +65,22 @@ class view_interface {
7265
template<class _D2 = _Derived>
7366
_LIBCPP_HIDE_FROM_ABI
7467
constexpr explicit operator bool()
75-
noexcept(noexcept(ranges::empty(declval<_D2>())))
76-
requires __can_empty<_D2>
68+
requires requires (_D2& __t) { ranges::empty(__t); }
7769
{
7870
return !ranges::empty(__derived());
7971
}
8072

8173
template<class _D2 = _Derived>
8274
_LIBCPP_HIDE_FROM_ABI
8375
constexpr explicit operator bool() const
84-
noexcept(noexcept(ranges::empty(declval<const _D2>())))
85-
requires __can_empty<const _D2>
76+
requires requires (const _D2& __t) { ranges::empty(__t); }
8677
{
8778
return !ranges::empty(__derived());
8879
}
8980

9081
template<class _D2 = _Derived>
9182
_LIBCPP_HIDE_FROM_ABI
9283
constexpr auto data()
93-
noexcept(noexcept(std::to_address(ranges::begin(__derived()))))
9484
requires contiguous_iterator<iterator_t<_D2>>
9585
{
9686
return std::to_address(ranges::begin(__derived()));
@@ -99,7 +89,6 @@ class view_interface {
9989
template<class _D2 = _Derived>
10090
_LIBCPP_HIDE_FROM_ABI
10191
constexpr auto data() const
102-
noexcept(noexcept(std::to_address(ranges::begin(__derived()))))
10392
requires range<const _D2> && contiguous_iterator<iterator_t<const _D2>>
10493
{
10594
return std::to_address(ranges::begin(__derived()));
@@ -108,27 +97,22 @@ class view_interface {
10897
template<class _D2 = _Derived>
10998
_LIBCPP_HIDE_FROM_ABI
11099
constexpr auto size()
111-
noexcept(noexcept(ranges::end(__derived()) - ranges::begin(__derived())))
112-
requires forward_range<_D2>
113-
&& sized_sentinel_for<sentinel_t<_D2>, iterator_t<_D2>>
100+
requires forward_range<_D2> && sized_sentinel_for<sentinel_t<_D2>, iterator_t<_D2>>
114101
{
115102
return ranges::end(__derived()) - ranges::begin(__derived());
116103
}
117104

118105
template<class _D2 = _Derived>
119106
_LIBCPP_HIDE_FROM_ABI
120107
constexpr auto size() const
121-
noexcept(noexcept(ranges::end(__derived()) - ranges::begin(__derived())))
122-
requires forward_range<const _D2>
123-
&& sized_sentinel_for<sentinel_t<const _D2>, iterator_t<const _D2>>
108+
requires forward_range<const _D2> && sized_sentinel_for<sentinel_t<const _D2>, iterator_t<const _D2>>
124109
{
125110
return ranges::end(__derived()) - ranges::begin(__derived());
126111
}
127112

128113
template<class _D2 = _Derived>
129114
_LIBCPP_HIDE_FROM_ABI
130115
constexpr decltype(auto) front()
131-
noexcept(noexcept(*ranges::begin(__derived())))
132116
requires forward_range<_D2>
133117
{
134118
_LIBCPP_ASSERT(!empty(),
@@ -139,7 +123,6 @@ class view_interface {
139123
template<class _D2 = _Derived>
140124
_LIBCPP_HIDE_FROM_ABI
141125
constexpr decltype(auto) front() const
142-
noexcept(noexcept(*ranges::begin(__derived())))
143126
requires forward_range<const _D2>
144127
{
145128
_LIBCPP_ASSERT(!empty(),
@@ -150,7 +133,6 @@ class view_interface {
150133
template<class _D2 = _Derived>
151134
_LIBCPP_HIDE_FROM_ABI
152135
constexpr decltype(auto) back()
153-
noexcept(noexcept(*ranges::prev(ranges::end(__derived()))))
154136
requires bidirectional_range<_D2> && common_range<_D2>
155137
{
156138
_LIBCPP_ASSERT(!empty(),
@@ -161,7 +143,6 @@ class view_interface {
161143
template<class _D2 = _Derived>
162144
_LIBCPP_HIDE_FROM_ABI
163145
constexpr decltype(auto) back() const
164-
noexcept(noexcept(*ranges::prev(ranges::end(__derived()))))
165146
requires bidirectional_range<const _D2> && common_range<const _D2>
166147
{
167148
_LIBCPP_ASSERT(!empty(),
@@ -172,15 +153,13 @@ class view_interface {
172153
template<random_access_range _RARange = _Derived>
173154
_LIBCPP_HIDE_FROM_ABI
174155
constexpr decltype(auto) operator[](range_difference_t<_RARange> __index)
175-
noexcept(noexcept(ranges::begin(__derived())[__index]))
176156
{
177157
return ranges::begin(__derived())[__index];
178158
}
179159

180160
template<random_access_range _RARange = const _Derived>
181161
_LIBCPP_HIDE_FROM_ABI
182162
constexpr decltype(auto) operator[](range_difference_t<_RARange> __index) const
183-
noexcept(noexcept(ranges::begin(__derived())[__index]))
184163
{
185164
return ranges::begin(__derived())[__index];
186165
}

libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -126,29 +126,27 @@ struct DataIsNull : std::ranges::view_interface<DataIsNull> {
126126
};
127127
static_assert(std::ranges::view<DataIsNull>);
128128

129-
template<bool IsNoexcept>
130-
struct BoolConvertibleComparison : std::ranges::view_interface<BoolConvertibleComparison<IsNoexcept>> {
129+
struct BoolConvertibleComparison : std::ranges::view_interface<BoolConvertibleComparison> {
131130
struct ResultType {
132131
bool value;
133-
constexpr operator bool() const noexcept(IsNoexcept) { return value; }
132+
constexpr operator bool() const { return value; }
134133
};
135134

136135
struct SentinelType {
137136
int *base_;
138-
SentinelType() = default;
139-
explicit constexpr SentinelType(int *base) : base_(base) {}
137+
explicit SentinelType() = default;
138+
constexpr explicit SentinelType(int *base) : base_(base) {}
140139
friend constexpr ResultType operator==(ForwardIter const& iter, SentinelType const& sent) noexcept { return {iter.base() == sent.base_}; }
141140
friend constexpr ResultType operator==(SentinelType const& sent, ForwardIter const& iter) noexcept { return {iter.base() == sent.base_}; }
142141
friend constexpr ResultType operator!=(ForwardIter const& iter, SentinelType const& sent) noexcept { return {iter.base() != sent.base_}; }
143142
friend constexpr ResultType operator!=(SentinelType const& sent, ForwardIter const& iter) noexcept { return {iter.base() != sent.base_}; }
144143
};
145144

146145
int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
147-
constexpr ForwardIter begin() const noexcept { return ForwardIter(const_cast<int*>(buff)); }
148-
constexpr SentinelType end() const noexcept { return SentinelType(const_cast<int*>(buff) + 8); }
146+
constexpr ForwardIter begin() const { return ForwardIter(const_cast<int*>(buff)); }
147+
constexpr SentinelType end() const { return SentinelType(const_cast<int*>(buff) + 8); }
149148
};
150-
static_assert(std::ranges::view<BoolConvertibleComparison<true>>);
151-
static_assert(std::ranges::view<BoolConvertibleComparison<false>>);
149+
static_assert(std::ranges::view<BoolConvertibleComparison>);
152150

153151
template<class T>
154152
concept EmptyInvocable = requires (T const& obj) { obj.empty(); };
@@ -189,19 +187,17 @@ constexpr bool testEmpty() {
189187
MoveOnlyForwardRange moveOnly;
190188
assert(!std::move(moveOnly).empty());
191189

192-
BoolConvertibleComparison<true> boolConv;
193-
BoolConvertibleComparison<false> boolConv2;
194-
LIBCPP_ASSERT_NOEXCEPT(boolConv.empty());
195-
ASSERT_NOT_NOEXCEPT(boolConv2.empty());
190+
BoolConvertibleComparison boolConv;
191+
ASSERT_NOT_NOEXCEPT(boolConv.empty());
196192

197193
assert(!boolConv.empty());
198-
assert(!static_cast<BoolConvertibleComparison<true> const&>(boolConv).empty());
194+
assert(!static_cast<const BoolConvertibleComparison&>(boolConv).empty());
199195

200196
assert(boolConv);
201-
assert(static_cast<BoolConvertibleComparison<true> const&>(boolConv));
197+
assert(static_cast<const BoolConvertibleComparison&>(boolConv));
202198

203199
assert(!std::ranges::empty(boolConv));
204-
assert(!std::ranges::empty(static_cast<BoolConvertibleComparison<true> const&>(boolConv)));
200+
assert(!std::ranges::empty(static_cast<const BoolConvertibleComparison&>(boolConv)));
205201

206202
return true;
207203
}

0 commit comments

Comments
 (0)