Skip to content

Commit 92d612c

Browse files
author
Patrick Palka
committed
libstdc++: Implement P2325 changes to default-constructibility of views
NB: This backport of r12-1606 to the 11 branch deliberately omits parts of P2325R3 so as to maximize backward compatibility with pre-P2325R3 code. In particular, we don't remove the default ctors for back_insert_iterator, front_insert_iterator, ostream_iterator, ref_view and basic_istream_view. === This implements the wording changes of P2325R3 "Views should not be required to be default constructible". Changes are relatively straightforward, besides perhaps those to __box (which now stands for copyable-box instead of semiregular-box) and __non_propagating_cache. For __box, this patch implements the recommended practice to also avoid std::optional when the boxed type is nothrow_move/copy_constructible. For __non_propagating_cache, now that it's used by split_view::_M_current, we need to add assignment from a value of the underlying type to the subset of the std::optional API implemented for the cache (needed by split_view::begin()). Hence the new __non_propagating_cache::operator= overload. In passing, this fixes the undesirable list-init in the constructors of the partial specialization of __box as reported in PR100475 comment gcc-mirror#7. PR libstdc++/103904 libstdc++-v3/ChangeLog: * include/bits/iterator_concepts.h (weakly_incrementable): Remove default_initializable requirement. * include/bits/ranges_base.h (ranges::view): Likewise. * include/bits/ranges_util.h (subrange): Constrain the default ctor. * include/bits/stl_iterator.h (common_iterator): Constrain the default ctor. (counted_iterator): Likewise. * include/std/ranges (__detail::__box::operator=): Handle self-assignment in the primary template. (__detail::__box): In the partial specialization: adjust constraints as per P2325. Add specialized operator= for the case when the wrapped type is not copyable. Constrain the default ctor. Avoid list-initialization. (single_view): Constraint the default ctor. (iota_view): Relax semiregular constraint to copyable. Constrain the default ctor. (iota_view::_Iterator): Constraint the default ctor. (ref_view): Remove the default ctor. Remove NSDMIs. (ref_view::_Iterator): Constrain the default ctor. (__detail::__non_propagating_cache::operator=): Define overload for assigning from a value of the underlying type. (filter_view): Likewise. (filter_view::_Iterator): Likewise. (transform_view): Likewise. (transform_view::_Iterator): Likewise. (take_view): Likewise. (take_view::_Iterator): Likewise. (take_while_view): Likewise. (take_while_view::_Iterator): Likewise. (drop_while_view): Likewise. (drop_while_view::_Iterator): Likewise. (join_view): Likewise. (split_view::_OuterIter::__current): Adjust after changing the type of _M_current. (split_view::_M_current): Wrap it in a __non_propagating_cache. (split_view::split_view): Constrain the default ctor. (common_view): Constrain the default ctor. (reverse_view): Likewise. (elements_view): Likewise. * include/std/span (enable_view<span<_ElementType, _Extent>>): Define this partial specialization to true unconditionally. * include/std/version (__cpp_lib_ranges): Adjust value. * testsuite/std/ranges/adaptors/detail/semiregular_box.cc: Rename to ... * testsuite/std/ranges/adaptors/detail/copyable_box.cc: ... this. (test02): Adjust now that __box is copyable-box not semiregular-box. (test03): New test. * testsuite/std/ranges/p2325.cc: New test. * testsuite/std/ranges/single_view.cc (test06): New test. * testsuite/std/ranges/view.cc: Adjust now that view doesn't require default_initializable. (cherry picked from commit 4b4f566)
1 parent 19d0e76 commit 92d612c

File tree

11 files changed

+349
-50
lines changed

11 files changed

+349
-50
lines changed

libstdc++-v3/include/bits/iterator_concepts.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -594,8 +594,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
594594

595595
/// Requirements on types that can be incremented with ++.
596596
template<typename _Iter>
597-
concept weakly_incrementable = default_initializable<_Iter>
598-
&& movable<_Iter>
597+
concept weakly_incrementable = movable<_Iter>
599598
&& requires(_Iter __i)
600599
{
601600
typename iter_difference_t<_Iter>;

libstdc++-v3/include/bits/ranges_base.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -619,8 +619,7 @@ namespace ranges
619619
/// [range.view] The ranges::view concept.
620620
template<typename _Tp>
621621
concept view
622-
= range<_Tp> && movable<_Tp> && default_initializable<_Tp>
623-
&& enable_view<_Tp>;
622+
= range<_Tp> && movable<_Tp> && enable_view<_Tp>;
624623

625624
// [range.refinements]
626625

libstdc++-v3/include/bits/ranges_util.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ namespace ranges
219219
[[no_unique_address]] _Size<__size_type> _M_size = {};
220220

221221
public:
222-
subrange() = default;
222+
subrange() requires default_initializable<_It> = default;
223223

224224
constexpr
225225
subrange(__detail::__convertible_to_non_slicing<_It> auto __i, _Sent __s)

libstdc++-v3/include/bits/stl_iterator.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1741,6 +1741,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
17411741
constexpr
17421742
common_iterator()
17431743
noexcept(is_nothrow_default_constructible_v<_It>)
1744+
requires default_initializable<_It>
17441745
: _M_it(), _M_index(0)
17451746
{ }
17461747

@@ -2118,7 +2119,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
21182119
// iterator_concept defined in __counted_iter_concept
21192120
// iterator_category defined in __counted_iter_cat
21202121

2121-
constexpr counted_iterator() = default;
2122+
constexpr counted_iterator() requires default_initializable<_It> = default;
21222123

21232124
constexpr
21242125
counted_iterator(_It __i, iter_difference_t<_It> __n)

libstdc++-v3/include/std/ranges

Lines changed: 98 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,13 @@ namespace ranges
113113
noexcept(is_nothrow_copy_constructible_v<_Tp>)
114114
requires (!copyable<_Tp>)
115115
{
116-
if ((bool)__that)
117-
this->emplace(*__that);
118-
else
119-
this->reset();
116+
if (this != std::__addressof(__that))
117+
{
118+
if ((bool)__that)
119+
this->emplace(*__that);
120+
else
121+
this->reset();
122+
}
120123
return *this;
121124
}
122125

@@ -125,37 +128,42 @@ namespace ranges
125128
noexcept(is_nothrow_move_constructible_v<_Tp>)
126129
requires (!movable<_Tp>)
127130
{
128-
if ((bool)__that)
129-
this->emplace(std::move(*__that));
130-
else
131-
this->reset();
131+
if (this != std::__addressof(__that))
132+
{
133+
if ((bool)__that)
134+
this->emplace(std::move(*__that));
135+
else
136+
this->reset();
137+
}
132138
return *this;
133139
}
134140
};
135141

136-
// For types which are already semiregular, this specialization of the
137-
// semiregular wrapper stores the object directly without going through
142+
// For types which are already copyable, this specialization of the
143+
// copyable wrapper stores the object directly without going through
138144
// std::optional. It provides just the subset of the primary template's
139145
// API that we currently use.
140-
template<__boxable _Tp> requires semiregular<_Tp>
146+
template<__boxable _Tp>
147+
requires copyable<_Tp> || (is_nothrow_move_constructible_v<_Tp>
148+
&& is_nothrow_copy_constructible_v<_Tp>)
141149
struct __box<_Tp>
142150
{
143151
private:
144152
[[no_unique_address]] _Tp _M_value = _Tp();
145153

146154
public:
147-
__box() = default;
155+
__box() requires default_initializable<_Tp> = default;
148156

149157
constexpr explicit
150158
__box(const _Tp& __t)
151159
noexcept(is_nothrow_copy_constructible_v<_Tp>)
152-
: _M_value{__t}
160+
: _M_value(__t)
153161
{ }
154162

155163
constexpr explicit
156164
__box(_Tp&& __t)
157165
noexcept(is_nothrow_move_constructible_v<_Tp>)
158-
: _M_value{std::move(__t)}
166+
: _M_value(std::move(__t))
159167
{ }
160168

161169
template<typename... _Args>
@@ -166,6 +174,38 @@ namespace ranges
166174
: _M_value(std::forward<_Args>(__args)...)
167175
{ }
168176

177+
__box(const __box&) = default;
178+
__box(__box&&) = default;
179+
__box& operator=(const __box&) requires copyable<_Tp> = default;
180+
__box& operator=(__box&&) requires copyable<_Tp> = default;
181+
182+
// When _Tp is nothrow_copy_constructible but not copy_assignable,
183+
// copy assignment is implemented via destroy-then-copy-construct.
184+
constexpr __box&
185+
operator=(const __box& __that) noexcept
186+
{
187+
static_assert(is_nothrow_copy_constructible_v<_Tp>);
188+
if (this != std::__addressof(__that))
189+
{
190+
_M_value.~_Tp();
191+
std::construct_at(std::__addressof(_M_value), *__that);
192+
}
193+
return *this;
194+
}
195+
196+
// Likewise for move assignment.
197+
constexpr __box&
198+
operator=(__box&& __that) noexcept
199+
{
200+
static_assert(is_nothrow_move_constructible_v<_Tp>);
201+
if (this != std::__addressof(__that))
202+
{
203+
_M_value.~_Tp();
204+
std::construct_at(std::__addressof(_M_value), std::move(*__that));
205+
}
206+
return *this;
207+
}
208+
169209
constexpr bool
170210
has_value() const noexcept
171211
{ return true; };
@@ -193,7 +233,7 @@ namespace ranges
193233
class single_view : public view_interface<single_view<_Tp>>
194234
{
195235
public:
196-
single_view() = default;
236+
single_view() requires default_initializable<_Tp> = default;
197237

198238
constexpr explicit
199239
single_view(const _Tp& __t)
@@ -305,7 +345,7 @@ namespace ranges
305345
template<weakly_incrementable _Winc,
306346
semiregular _Bound = unreachable_sentinel_t>
307347
requires std::__detail::__weakly_eq_cmp_with<_Winc, _Bound>
308-
&& semiregular<_Winc>
348+
&& copyable<_Winc>
309349
class iota_view : public view_interface<iota_view<_Winc, _Bound>>
310350
{
311351
private:
@@ -334,7 +374,7 @@ namespace ranges
334374
using value_type = _Winc;
335375
using difference_type = __detail::__iota_diff_t<_Winc>;
336376

337-
_Iterator() = default;
377+
_Iterator() requires default_initializable<_Winc> = default;
338378

339379
constexpr explicit
340380
_Iterator(_Winc __value)
@@ -531,7 +571,7 @@ namespace ranges
531571
[[no_unique_address]] _Bound _M_bound = _Bound();
532572

533573
public:
534-
iota_view() = default;
574+
iota_view() requires default_initializable<_Winc> = default;
535575

536576
constexpr explicit
537577
iota_view(_Winc __value)
@@ -1140,6 +1180,16 @@ namespace views::__adaptor
11401180
return *this;
11411181
}
11421182

1183+
constexpr __non_propagating_cache&
1184+
operator=(_Tp __val)
1185+
{
1186+
this->_M_reset();
1187+
std::construct_at(std::__addressof(this->_M_payload._M_payload),
1188+
std::in_place, std::move(__val));
1189+
this->_M_payload._M_engaged = true;
1190+
return *this;
1191+
}
1192+
11431193
constexpr _Tp&
11441194
operator*() noexcept
11451195
{ return this->_M_get(); }
@@ -1317,7 +1367,7 @@ namespace views::__adaptor
13171367
using value_type = range_value_t<_Vp>;
13181368
using difference_type = range_difference_t<_Vp>;
13191369

1320-
_Iterator() = default;
1370+
_Iterator() requires default_initializable<_Vp_iter> = default;
13211371

13221372
constexpr
13231373
_Iterator(filter_view* __parent, _Vp_iter __current)
@@ -1429,7 +1479,9 @@ namespace views::__adaptor
14291479
_Vp _M_base = _Vp();
14301480

14311481
public:
1432-
filter_view() = default;
1482+
filter_view() requires (default_initializable<_Vp>
1483+
&& default_initializable<_Pred>)
1484+
= default;
14331485

14341486
constexpr
14351487
filter_view(_Vp __base, _Pred __pred)
@@ -1578,7 +1630,7 @@ namespace views::__adaptor
15781630
= remove_cvref_t<invoke_result_t<_Fp&, range_reference_t<_Base>>>;
15791631
using difference_type = range_difference_t<_Base>;
15801632

1581-
_Iterator() = default;
1633+
_Iterator() requires default_initializable<_Base_iter> = default;
15821634

15831635
constexpr
15841636
_Iterator(_Parent* __parent, _Base_iter __current)
@@ -1793,7 +1845,9 @@ namespace views::__adaptor
17931845
_Vp _M_base = _Vp();
17941846

17951847
public:
1796-
transform_view() = default;
1848+
transform_view() requires (default_initializable<_Vp>
1849+
&& default_initializable<_Fp>)
1850+
= default;
17971851

17981852
constexpr
17991853
transform_view(_Vp __base, _Fp __fun)
@@ -1928,7 +1982,7 @@ namespace views::__adaptor
19281982
_Vp _M_base = _Vp();
19291983

19301984
public:
1931-
take_view() = default;
1985+
take_view() requires default_initializable<_Vp> = default;
19321986

19331987
constexpr
19341988
take_view(_Vp base, range_difference_t<_Vp> __count)
@@ -2112,7 +2166,9 @@ namespace views::__adaptor
21122166
_Vp _M_base = _Vp();
21132167

21142168
public:
2115-
take_while_view() = default;
2169+
take_while_view() requires (default_initializable<_Vp>
2170+
&& default_initializable<_Pred>)
2171+
= default;
21162172

21172173
constexpr
21182174
take_while_view(_Vp base, _Pred __pred)
@@ -2200,7 +2256,7 @@ namespace views::__adaptor
22002256
_M_cached_begin;
22012257

22022258
public:
2203-
drop_view() = default;
2259+
drop_view() requires default_initializable<_Vp> = default;
22042260

22052261
constexpr
22062262
drop_view(_Vp __base, range_difference_t<_Vp> __count)
@@ -2316,7 +2372,9 @@ namespace views::__adaptor
23162372
_Vp _M_base = _Vp();
23172373

23182374
public:
2319-
drop_while_view() = default;
2375+
drop_while_view() requires (default_initializable<_Vp>
2376+
&& default_initializable<_Pred>)
2377+
= default;
23202378

23212379
constexpr
23222380
drop_while_view(_Vp __base, _Pred __pred)
@@ -2506,7 +2564,9 @@ namespace views::__adaptor
25062564
= common_type_t<range_difference_t<_Base>,
25072565
range_difference_t<range_reference_t<_Base>>>;
25082566

2509-
_Iterator() = default;
2567+
_Iterator() requires (default_initializable<_Outer_iter>
2568+
&& default_initializable<_Inner_iter>)
2569+
= default;
25102570

25112571
constexpr
25122572
_Iterator(_Parent* __parent, _Outer_iter __outer)
@@ -2659,7 +2719,7 @@ namespace views::__adaptor
26592719
_Vp _M_base = _Vp();
26602720

26612721
public:
2662-
join_view() = default;
2722+
join_view() requires default_initializable<_Vp> = default;
26632723

26642724
constexpr explicit
26652725
join_view(_Vp __base)
@@ -2826,7 +2886,7 @@ namespace views::__adaptor
28262886
if constexpr (forward_range<_Vp>)
28272887
return _M_current;
28282888
else
2829-
return _M_parent->_M_current;
2889+
return *_M_parent->_M_current;
28302890
}
28312891

28322892
constexpr auto&
@@ -2835,7 +2895,7 @@ namespace views::__adaptor
28352895
if constexpr (forward_range<_Vp>)
28362896
return _M_current;
28372897
else
2838-
return _M_parent->_M_current;
2898+
return *_M_parent->_M_current;
28392899
}
28402900

28412901
_Parent* _M_parent = nullptr;
@@ -3083,12 +3143,14 @@ namespace views::__adaptor
30833143
// XXX: _M_current is "present only if !forward_range<V>"
30843144
[[no_unique_address]]
30853145
__detail::__maybe_present_t<!forward_range<_Vp>,
3086-
iterator_t<_Vp>> _M_current;
3146+
__detail::__non_propagating_cache<iterator_t<_Vp>>> _M_current;
30873147
_Vp _M_base = _Vp();
30883148

30893149

30903150
public:
3091-
split_view() = default;
3151+
split_view() requires (default_initializable<_Vp>
3152+
&& default_initializable<_Pattern>)
3153+
= default;
30923154

30933155
constexpr
30943156
split_view(_Vp __base, _Pattern __pattern)
@@ -3219,7 +3281,7 @@ namespace views::__adaptor
32193281
_Vp _M_base = _Vp();
32203282

32213283
public:
3222-
common_view() = default;
3284+
common_view() requires default_initializable<_Vp> = default;
32233285

32243286
constexpr explicit
32253287
common_view(_Vp __r)
@@ -3348,7 +3410,7 @@ namespace views::__adaptor
33483410
_Vp _M_base = _Vp();
33493411

33503412
public:
3351-
reverse_view() = default;
3413+
reverse_view() requires default_initializable<_Vp> = default;
33523414

33533415
constexpr explicit
33543416
reverse_view(_Vp __r)
@@ -3490,7 +3552,7 @@ namespace views::__adaptor
34903552
class elements_view : public view_interface<elements_view<_Vp, _Nm>>
34913553
{
34923554
public:
3493-
elements_view() = default;
3555+
elements_view() requires default_initializable<_Vp> = default;
34943556

34953557
constexpr explicit
34963558
elements_view(_Vp base)
@@ -3611,7 +3673,7 @@ namespace views::__adaptor
36113673
= remove_cvref_t<tuple_element_t<_Nm, range_value_t<_Base>>>;
36123674
using difference_type = range_difference_t<_Base>;
36133675

3614-
_Iterator() = default;
3676+
_Iterator() requires default_initializable<iterator_t<_Base>> = default;
36153677

36163678
constexpr explicit
36173679
_Iterator(iterator_t<_Base> current)

libstdc++-v3/include/std/span

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -450,8 +450,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
450450
// Opt-in to view concept
451451
template<typename _ElementType, size_t _Extent>
452452
inline constexpr bool
453-
enable_view<span<_ElementType, _Extent>>
454-
= _Extent == 0 || _Extent == dynamic_extent;
453+
enable_view<span<_ElementType, _Extent>> = true;
455454
}
456455
_GLIBCXX_END_NAMESPACE_VERSION
457456
} // namespace std

libstdc++-v3/include/std/version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@
247247
#define __cpp_lib_optional 202106L
248248
#define __cpp_lib_polymorphic_allocator 201902L
249249
#if __cpp_lib_concepts
250-
# define __cpp_lib_ranges 201911L
250+
# define __cpp_lib_ranges 202106L
251251
#endif
252252
#if __cpp_lib_atomic_wait || _GLIBCXX_HAVE_POSIX_SEMAPHORE
253253
# define __cpp_lib_semaphore 201907L

0 commit comments

Comments
 (0)