Skip to content

Commit 03515b4

Browse files
authored
Merge 2019-02 LWG Motion 16
P1252R2 Ranges Design Cleanup Fixes #2707.
2 parents c1b185e + 0b06fcd commit 03515b4

File tree

6 files changed

+441
-388
lines changed

6 files changed

+441
-388
lines changed

source/algorithms.tex

Lines changed: 292 additions & 216 deletions
Large diffs are not rendered by default.

source/future.tex

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,6 +1515,32 @@
15151515
\end{codeblock}
15161516
\end{example}
15171517

1518+
\rSec1[depr.move.iter.elem]{Deprecated \tcode{move_iterator} access}
1519+
1520+
\pnum
1521+
The following member is declared in addition to those members
1522+
specified in \ref{move.iter.elem}:
1523+
1524+
\begin{codeblock}
1525+
namespace std {
1526+
template<class Iterator>
1527+
class move_iterator {
1528+
public:
1529+
constexpr pointer operator->() const;
1530+
};
1531+
}
1532+
\end{codeblock}
1533+
1534+
\indexlibrarymember{operator->}{move_iterator}%
1535+
\begin{itemdecl}
1536+
constexpr pointer operator->() const;
1537+
\end{itemdecl}
1538+
1539+
\begin{itemdescr}
1540+
\pnum
1541+
\returns \tcode{current}.
1542+
\end{itemdescr}
1543+
15181544
\rSec1[depr.util.smartptr.shared.atomic]{Deprecated \tcode{shared_ptr} atomic access}
15191545

15201546
\pnum

source/iterators.tex

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -197,11 +197,11 @@
197197

198198
// \ref{alg.req.mergeable}, concept \tcode{Mergeable}
199199
template<class I1, class I2, class Out,
200-
class R = ranges::less<>, class P1 = identity, class P2 = identity>
200+
class R = ranges::less, class P1 = identity, class P2 = identity>
201201
concept Mergeable = @\seebelow@;
202202

203203
// \ref{alg.req.sortable}, concept \tcode{Sortable}
204-
template<class I, class R = ranges::less<>, class P = identity>
204+
template<class I, class R = ranges::less, class P = identity>
205205
concept Sortable = @\seebelow@;
206206

207207
// \ref{iterator.primitives}, primitives
@@ -2277,7 +2277,7 @@
22772277

22782278
\pnum
22792279
\begin{note}
2280-
The \tcode{ranges::less<>} function object type
2280+
The \tcode{ranges::less} function object type
22812281
used in the concepts below imposes constraints on the concepts' arguments
22822282
in addition to those that appear in the concepts' bodies\iref{range.cmp}.
22832283
\end{note}
@@ -2428,7 +2428,7 @@
24282428

24292429
\indexlibrary{\idxcode{Mergeable}}%
24302430
\begin{codeblock}
2431-
template<class I1, class I2, class Out, class R = ranges::less<>,
2431+
template<class I1, class I2, class Out, class R = ranges::less,
24322432
class P1 = identity, class P2 = identity>
24332433
concept Mergeable =
24342434
InputIterator<I1> &&
@@ -2447,7 +2447,7 @@
24472447

24482448
\indexlibrary{\idxcode{Sortable}}%
24492449
\begin{codeblock}
2450-
template<class I, class R = ranges::less<>, class P = identity>
2450+
template<class I, class R = ranges::less, class P = identity>
24512451
concept Sortable =
24522452
Permutable<I> &&
24532453
IndirectStrictWeakOrder<R, projected<I, P>>;
@@ -3909,7 +3909,6 @@
39093909

39103910
constexpr iterator_type base() const;
39113911
constexpr reference operator*() const;
3912-
constexpr pointer operator->() const;
39133912

39143913
constexpr move_iterator& operator++();
39153914
constexpr auto operator++(int);
@@ -4062,16 +4061,6 @@
40624061
\effects Equivalent to: \tcode{return ranges::iter_move(current);}
40634062
\end{itemdescr}
40644063

4065-
\indexlibrarymember{operator->}{move_iterator}%
4066-
\begin{itemdecl}
4067-
constexpr pointer operator->() const;
4068-
\end{itemdecl}
4069-
4070-
\begin{itemdescr}
4071-
\pnum
4072-
\returns \tcode{current}.
4073-
\end{itemdescr}
4074-
40754064
\indexlibrarymember{operator[]}{move_iterator}%
40764065
\begin{itemdecl}
40774066
constexpr reference operator[](difference_type n) const;

source/lib-intro.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@
338338
\begin{example}
339339
\begin{codeblock}
340340
std::pair<int, std::string_view> pairs[] = {{2, "foo"}, {1, "bar"}, {0, "baz"}};
341-
std::ranges::sort(pairs, std::ranges::less<>{}, [](auto const& p) { return p.first; });
341+
std::ranges::sort(pairs, std::ranges::less{}, [](auto const& p) { return p.first; });
342342
\end{codeblock}
343343
sorts the pairs in increasing order of their \tcode{first} members:
344344
\begin{codeblock}

source/ranges.tex

Lines changed: 100 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,6 @@
5353
template<class T>
5454
using sentinel_t = decltype(ranges::end(declval<T&>()));
5555

56-
template<@\placeholder{forwarding-range}@ R>
57-
using safe_iterator_t = iterator_t<R>;
58-
5956
template<class T>
6057
concept Range = @\seebelow@;
6158

@@ -112,8 +109,15 @@
112109
requires (K == subrange_kind::sized || !SizedSentinel<S, I>)
113110
class subrange;
114111

115-
template<@\placeholder{forwarding-range}@ R>
116-
using safe_subrange_t = subrange<iterator_t<R>>;
112+
// \ref{range.dangling}, dangling iterator handling
113+
struct dangling;
114+
115+
template<Range R>
116+
using safe_iterator_t = conditional_t<@\placeholder{forwarding-range}@<R>, iterator_t<R>, dangling>;
117+
118+
template<Range R>
119+
using safe_subrange_t =
120+
conditional_t<@\placeholder{forwarding-range}@<R>, subrange<iterator_t<R>>, dangling>;
117121

118122
// \ref{range.empty}, empty view
119123
template<class T>
@@ -145,6 +149,10 @@
145149
template<ViewableRange R>
146150
using all_view = decltype(view::all(declval<R>()));
147151

152+
template<Range R>
153+
requires is_object_v<R>
154+
class ref_view;
155+
148156
// \ref{range.filter}, filter view
149157
template<InputRange V, IndirectUnaryPredicate<iterator_t<V>> Pred>
150158
requires View<V> && is_object_v<Pred>
@@ -180,7 +188,7 @@
180188

181189
template<InputRange V, ForwardRange Pattern>
182190
requires View<V> && View<Pattern> &&
183-
IndirectlyComparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to<>> &&
191+
IndirectlyComparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
184192
(ForwardRange<V> || @\placeholder{tiny-range}@<Pattern>)
185193
class split_view;
186194

@@ -1440,6 +1448,48 @@
14401448
\end{codeblock}
14411449
\end{itemdescr}
14421450

1451+
\rSec2[range.dangling]{Dangling iterator handling}
1452+
1453+
\pnum
1454+
The tag type \tcode{dangling} is used together
1455+
with the template aliases \tcode{safe_iterator_t} and \tcode{safe_subrange_t}
1456+
to indicate that an algorithm
1457+
that typically returns an iterator into or subrange of a \tcode{Range} argument
1458+
does not return an iterator or subrange
1459+
which could potentially reference a range
1460+
whose lifetime has ended for a particular rvalue \tcode{Range} argument
1461+
which does not model \tcode{\placeholder{forwarding-range}}\iref{range.range}.
1462+
\begin{codeblock}
1463+
namespace std {
1464+
struct dangling {
1465+
constexpr dangling() noexcept = default;
1466+
template<class... Args>
1467+
constexpr dangling(Args&&...) noexcept { }
1468+
};
1469+
}
1470+
\end{codeblock}
1471+
1472+
\pnum
1473+
\begin{example}
1474+
\begin{codeblock}
1475+
vector<int> f();
1476+
auto result1 = ranges::find(f(), 42); // \#1
1477+
static_assert(Same<decltype(result1), dangling>);
1478+
auto vec = f();
1479+
auto result2 = ranges::find(vec, 42); // \#2
1480+
static_assert(Same<decltype(result2), vector<int>::iterator>);
1481+
auto result3 = ranges::find(subrange{vec}, 42); // \#3
1482+
static_assert(Same<decltype(result3), vector<int>::iterator>);
1483+
\end{codeblock}
1484+
The call to \tcode{ranges::find} at \#1 returns \tcode{dangling}
1485+
since \tcode{f()} is an rvalue \tcode{vector};
1486+
the \tcode{vector} could potentially be destroyed
1487+
before a returned iterator is dereferenced.
1488+
However, the calls at \#2 and \#3 both return iterators
1489+
since the lvalue \tcode{vec} and specializations of \tcode{subrange}
1490+
model \tcode{\placeholder{forwarding-range}}.
1491+
\end{example}
1492+
14431493
\rSec1[range.factories]{Range factories}
14441494

14451495
\pnum
@@ -2347,28 +2397,28 @@
23472397
\item \tcode{\placeholdernc{decay-copy}(E)} if the decayed type of \tcode{E}
23482398
models \libconcept{View}.
23492399

2350-
\item Otherwise, \tcode{\placeholder{ref-view}\{E\}} if that
2351-
expression is well-formed, where \tcode{\placeholder{ref-view}}
2352-
is the exposition-only \libconcept{View} specified below.
2400+
\item Otherwise, \tcode{ref_view\{E\}} if that expression is well-formed.
23532401

23542402
\item Otherwise, \tcode{subrange\{E\}}.
23552403
\end{itemize}
23562404

2357-
\rSec3[range.view.ref]{\placeholder{ref-view}}
2405+
\rSec3[range.ref.view]{Class template \tcode{ref_view}}
23582406

2407+
\pnum
2408+
\tcode{ref_view} is a \tcode{View} of the elements of some other \tcode{Range}.
23592409
\begin{codeblock}
23602410
namespace std::ranges {
23612411
template<Range R>
23622412
requires is_object_v<R>
2363-
class @\placeholder{ref-view}@ : public view_interface<@\placeholder{ref-view}@<R>> {
2413+
class ref_view : public view_interface<ref_view<R>> {
23642414
private:
23652415
R* r_ = nullptr; // \expos
23662416
public:
2367-
constexpr @\placeholdernc{ref-view}@() noexcept = default;
2417+
constexpr ref_view() noexcept = default;
23682418

2369-
template<@\placeholder{not-same-as}@<@\placeholder{ref-view}@> T>
2419+
template<@\placeholder{not-same-as}@<ref_view> T>
23702420
requires @\seebelow@
2371-
constexpr @\placeholder{ref-view}@(T&& t);
2421+
constexpr ref_view(T&& t);
23722422

23732423
constexpr R& base() const { return *r_; }
23742424

@@ -2385,22 +2435,22 @@
23852435
constexpr auto data() const requires ContiguousRange<R>
23862436
{ return ranges::data(*r_); }
23872437

2388-
friend constexpr iterator_t<R> begin(@\placeholder{ref-view}@ r)
2438+
friend constexpr iterator_t<R> begin(ref_view r)
23892439
{ return r.begin(); }
23902440

2391-
friend constexpr sentinel_t<R> end(@\placeholder{ref-view}@ r)
2441+
friend constexpr sentinel_t<R> end(ref_view r)
23922442
{ return r.end(); }
23932443
};
23942444
template<class R>
2395-
@\placeholder{ref-view}@(R&) -> @\placeholder{ref-view}@<R>;
2445+
ref_view(R&) -> ref_view<R>;
23962446
}
23972447
\end{codeblock}
23982448

2399-
\indexlibrary{\idxcode{\placeholder{ref-view}}!\idxcode{\placeholder{ref-view}}}%
2449+
\indexlibrary{\idxcode{ref_view}}%
24002450
\begin{itemdecl}
2401-
template<@\placeholder{not-same-as}@<@\placeholder{ref-view}@> T>
2451+
template<@\placeholder{not-same-as}@<ref_view> T>
24022452
requires @\seebelow@
2403-
constexpr @\placeholder{ref-view}@(T&& t);
2453+
constexpr ref_view(T&& t);
24042454
\end{itemdecl}
24052455

24062456
\begin{itemdescr}
@@ -4308,7 +4358,7 @@
43084358

43094359
template<InputRange V, ForwardRange Pattern>
43104360
requires View<V> && View<Pattern> &&
4311-
IndirectlyComparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to<>> &&
4361+
IndirectlyComparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
43124362
(ForwardRange<V> || @\placeholdernc{tiny-range}@<Pattern>)
43134363
class split_view : public view_interface<split_view<V, Pattern>> {
43144364
private:
@@ -5113,5 +5163,32 @@
51135163
The name \tcode{view::reverse} denotes a
51145164
range adaptor object\iref{range.adaptor.object}.
51155165
For some subexpression \tcode{E}, the expression
5116-
\tcode{view::reverse(E)} is expression-equivalent to
5117-
\tcode{reverse_view\{E\}}.
5166+
\tcode{view::reverse(E)} is expression-equivalent to:
5167+
\begin{itemize}
5168+
\item
5169+
If the type of \tcode{E} is
5170+
a (possibly cv-qualified) specialization of \tcode{reverse_view},
5171+
equivalent to \tcode{E.base()}.
5172+
\item
5173+
Otherwise, if the type of \tcode{E} is cv-qualified
5174+
\begin{codeblock}
5175+
subrange<reverse_iterator<I>, reverse_iterator<I>, K>
5176+
\end{codeblock}
5177+
for some iterator type \tcode{I} and
5178+
value \tcode{K} of type \tcode{subrange_kind},
5179+
\begin{itemize}
5180+
\item
5181+
if \tcode{K} is \tcode{subrange_kind::sized}, equivalent to:
5182+
\begin{codeblock}
5183+
subrange<I, I, K>(E.end().base(), E.begin().base(), E.size())
5184+
\end{codeblock}
5185+
\item
5186+
otherwise, equivalent to:
5187+
\begin{codeblock}
5188+
subrange<I, I, K>(E.end().base(), E.begin().base())
5189+
\end{codeblock}
5190+
\end{itemize}
5191+
However, in either case \tcode{E} is evaluated only once.
5192+
\item
5193+
Otherwise, equivalent to \tcode{reverse_view\{E\}}.
5194+
\end{itemize}

0 commit comments

Comments
 (0)