|
53 | 53 | template<class T>
|
54 | 54 | using sentinel_t = decltype(ranges::end(declval<T&>()));
|
55 | 55 |
|
56 |
| - template<@\placeholder{forwarding-range}@ R> |
57 |
| - using safe_iterator_t = iterator_t<R>; |
58 |
| - |
59 | 56 | template<class T>
|
60 | 57 | concept Range = @\seebelow@;
|
61 | 58 |
|
|
112 | 109 | requires (K == subrange_kind::sized || !SizedSentinel<S, I>)
|
113 | 110 | class subrange;
|
114 | 111 |
|
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>; |
117 | 121 |
|
118 | 122 | // \ref{range.empty}, empty view
|
119 | 123 | template<class T>
|
|
145 | 149 | template<ViewableRange R>
|
146 | 150 | using all_view = decltype(view::all(declval<R>()));
|
147 | 151 |
|
| 152 | + template<Range R> |
| 153 | + requires is_object_v<R> |
| 154 | + class ref_view; |
| 155 | + |
148 | 156 | // \ref{range.filter}, filter view
|
149 | 157 | template<InputRange V, IndirectUnaryPredicate<iterator_t<V>> Pred>
|
150 | 158 | requires View<V> && is_object_v<Pred>
|
|
180 | 188 |
|
181 | 189 | template<InputRange V, ForwardRange Pattern>
|
182 | 190 | 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> && |
184 | 192 | (ForwardRange<V> || @\placeholder{tiny-range}@<Pattern>)
|
185 | 193 | class split_view;
|
186 | 194 |
|
|
1440 | 1448 | \end{codeblock}
|
1441 | 1449 | \end{itemdescr}
|
1442 | 1450 |
|
| 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 | + |
1443 | 1493 | \rSec1[range.factories]{Range factories}
|
1444 | 1494 |
|
1445 | 1495 | \pnum
|
|
2347 | 2397 | \item \tcode{\placeholdernc{decay-copy}(E)} if the decayed type of \tcode{E}
|
2348 | 2398 | models \libconcept{View}.
|
2349 | 2399 |
|
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. |
2353 | 2401 |
|
2354 | 2402 | \item Otherwise, \tcode{subrange\{E\}}.
|
2355 | 2403 | \end{itemize}
|
2356 | 2404 |
|
2357 |
| -\rSec3[range.view.ref]{\placeholder{ref-view}} |
| 2405 | +\rSec3[range.ref.view]{Class template \tcode{ref_view}} |
2358 | 2406 |
|
| 2407 | +\pnum |
| 2408 | +\tcode{ref_view} is a \tcode{View} of the elements of some other \tcode{Range}. |
2359 | 2409 | \begin{codeblock}
|
2360 | 2410 | namespace std::ranges {
|
2361 | 2411 | template<Range R>
|
2362 | 2412 | 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>> { |
2364 | 2414 | private:
|
2365 | 2415 | R* r_ = nullptr; // \expos
|
2366 | 2416 | public:
|
2367 |
| - constexpr @\placeholdernc{ref-view}@() noexcept = default; |
| 2417 | + constexpr ref_view() noexcept = default; |
2368 | 2418 |
|
2369 |
| - template<@\placeholder{not-same-as}@<@\placeholder{ref-view}@> T> |
| 2419 | + template<@\placeholder{not-same-as}@<ref_view> T> |
2370 | 2420 | requires @\seebelow@
|
2371 |
| - constexpr @\placeholder{ref-view}@(T&& t); |
| 2421 | + constexpr ref_view(T&& t); |
2372 | 2422 |
|
2373 | 2423 | constexpr R& base() const { return *r_; }
|
2374 | 2424 |
|
|
2385 | 2435 | constexpr auto data() const requires ContiguousRange<R>
|
2386 | 2436 | { return ranges::data(*r_); }
|
2387 | 2437 |
|
2388 |
| - friend constexpr iterator_t<R> begin(@\placeholder{ref-view}@ r) |
| 2438 | + friend constexpr iterator_t<R> begin(ref_view r) |
2389 | 2439 | { return r.begin(); }
|
2390 | 2440 |
|
2391 |
| - friend constexpr sentinel_t<R> end(@\placeholder{ref-view}@ r) |
| 2441 | + friend constexpr sentinel_t<R> end(ref_view r) |
2392 | 2442 | { return r.end(); }
|
2393 | 2443 | };
|
2394 | 2444 | template<class R>
|
2395 |
| - @\placeholder{ref-view}@(R&) -> @\placeholder{ref-view}@<R>; |
| 2445 | + ref_view(R&) -> ref_view<R>; |
2396 | 2446 | }
|
2397 | 2447 | \end{codeblock}
|
2398 | 2448 |
|
2399 |
| -\indexlibrary{\idxcode{\placeholder{ref-view}}!\idxcode{\placeholder{ref-view}}}% |
| 2449 | +\indexlibrary{\idxcode{ref_view}}% |
2400 | 2450 | \begin{itemdecl}
|
2401 |
| -template<@\placeholder{not-same-as}@<@\placeholder{ref-view}@> T> |
| 2451 | +template<@\placeholder{not-same-as}@<ref_view> T> |
2402 | 2452 | requires @\seebelow@
|
2403 |
| -constexpr @\placeholder{ref-view}@(T&& t); |
| 2453 | +constexpr ref_view(T&& t); |
2404 | 2454 | \end{itemdecl}
|
2405 | 2455 |
|
2406 | 2456 | \begin{itemdescr}
|
|
4308 | 4358 |
|
4309 | 4359 | template<InputRange V, ForwardRange Pattern>
|
4310 | 4360 | 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> && |
4312 | 4362 | (ForwardRange<V> || @\placeholdernc{tiny-range}@<Pattern>)
|
4313 | 4363 | class split_view : public view_interface<split_view<V, Pattern>> {
|
4314 | 4364 | private:
|
|
5113 | 5163 | The name \tcode{view::reverse} denotes a
|
5114 | 5164 | range adaptor object\iref{range.adaptor.object}.
|
5115 | 5165 | 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