tmp/tmpkqe7wrqj/{from.md → to.md}
RENAMED
|
@@ -1,21 +1,20 @@
|
|
| 1 |
### Dangling iterator handling <a id="range.dangling">[[range.dangling]]</a>
|
| 2 |
|
| 3 |
-
The
|
| 4 |
-
`borrowed_iterator_t` and `borrowed_subrange_t`
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
|
| 11 |
``` cpp
|
| 12 |
namespace std::ranges {
|
| 13 |
struct dangling {
|
| 14 |
constexpr dangling() noexcept = default;
|
| 15 |
-
|
| 16 |
-
constexpr dangling(Args&&...) noexcept { }
|
| 17 |
};
|
| 18 |
}
|
| 19 |
```
|
| 20 |
|
| 21 |
[*Example 1*:
|
|
@@ -25,17 +24,25 @@ vector<int> f();
|
|
| 25 |
auto result1 = ranges::find(f(), 42); // #1
|
| 26 |
static_assert(same_as<decltype(result1), ranges::dangling>);
|
| 27 |
auto vec = f();
|
| 28 |
auto result2 = ranges::find(vec, 42); // #2
|
| 29 |
static_assert(same_as<decltype(result2), vector<int>::iterator>);
|
| 30 |
-
auto result3 = ranges::find(subrange{vec}, 42);
|
| 31 |
static_assert(same_as<decltype(result3), vector<int>::iterator>);
|
| 32 |
```
|
| 33 |
|
| 34 |
The call to `ranges::find` at \#1 returns `ranges::dangling` since `f()`
|
| 35 |
-
is an rvalue `vector`; the `vector`
|
| 36 |
before a returned iterator is dereferenced. However, the calls at \#2
|
| 37 |
and \#3 both return iterators since the lvalue `vec` and specializations
|
| 38 |
of `subrange` model `borrowed_range`.
|
| 39 |
|
| 40 |
— *end example*]
|
| 41 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
### Dangling iterator handling <a id="range.dangling">[[range.dangling]]</a>
|
| 2 |
|
| 3 |
+
The type `dangling` is used together with the template aliases
|
| 4 |
+
`borrowed_iterator_t` and `borrowed_subrange_t`. When an algorithm that
|
| 5 |
+
typically returns an iterator into, or a subrange of, a range argument
|
| 6 |
+
is called with an rvalue range argument that does not model
|
| 7 |
+
`borrowed_range` [[range.range]], the return value possibly refers to a
|
| 8 |
+
range whose lifetime has ended. In such cases, the type `dangling` is
|
| 9 |
+
returned instead of an iterator or subrange.
|
| 10 |
|
| 11 |
``` cpp
|
| 12 |
namespace std::ranges {
|
| 13 |
struct dangling {
|
| 14 |
constexpr dangling() noexcept = default;
|
| 15 |
+
constexpr dangling(auto&&...) noexcept {}
|
|
|
|
| 16 |
};
|
| 17 |
}
|
| 18 |
```
|
| 19 |
|
| 20 |
[*Example 1*:
|
|
|
|
| 24 |
auto result1 = ranges::find(f(), 42); // #1
|
| 25 |
static_assert(same_as<decltype(result1), ranges::dangling>);
|
| 26 |
auto vec = f();
|
| 27 |
auto result2 = ranges::find(vec, 42); // #2
|
| 28 |
static_assert(same_as<decltype(result2), vector<int>::iterator>);
|
| 29 |
+
auto result3 = ranges::find(ranges::subrange{vec}, 42); // #3
|
| 30 |
static_assert(same_as<decltype(result3), vector<int>::iterator>);
|
| 31 |
```
|
| 32 |
|
| 33 |
The call to `ranges::find` at \#1 returns `ranges::dangling` since `f()`
|
| 34 |
+
is an rvalue `vector`; it is possible for the `vector` to be destroyed
|
| 35 |
before a returned iterator is dereferenced. However, the calls at \#2
|
| 36 |
and \#3 both return iterators since the lvalue `vec` and specializations
|
| 37 |
of `subrange` model `borrowed_range`.
|
| 38 |
|
| 39 |
— *end example*]
|
| 40 |
|
| 41 |
+
For a type `R` that models `range`:
|
| 42 |
+
|
| 43 |
+
- if `R` models `borrowed_range`, then `borrowed_iterator_t<R>` denotes
|
| 44 |
+
`iterator_t<R>`, and `borrowed_subrange_t<R>` denotes
|
| 45 |
+
`subrange<iterator_t<R>>`;
|
| 46 |
+
- otherwise, both `borrowed_iterator_t<R>` and `borrowed_subrange_t<R>`
|
| 47 |
+
denote `dangling`.
|
| 48 |
+
|