25 Ranges library [ranges]

25.5 Range utilities [range.utility]

25.5.5 Dangling iterator handling [range.dangling]

The type dangling is used together with the template aliases borrowed_iterator_t and borrowed_subrange_t.
When an algorithm that typically returns an iterator into, or a subrange of, a range argument is called with an rvalue range argument that does not model borrowed_range ([range.range]), the return value possibly refers to a range whose lifetime has ended.
In such cases, the type dangling is returned instead of an iterator or subrange.
namespace std::ranges { struct dangling { constexpr dangling() noexcept = default; constexpr dangling(auto&&...) noexcept {} }; }
[Example 1: vector<int> f(); auto result1 = ranges::find(f(), 42); // #1 static_assert(same_as<decltype(result1), ranges::dangling>); auto vec = f(); auto result2 = ranges::find(vec, 42); // #2 static_assert(same_as<decltype(result2), vector<int>::iterator>); auto result3 = ranges::find(ranges::subrange{vec}, 42); // #3 static_assert(same_as<decltype(result3), vector<int>::iterator>);
The call to ranges​::​find at #1 returns ranges​::​dangling since f() is an rvalue vector; it is possible for the vector to be destroyed before a returned iterator is dereferenced.
However, the calls at #2 and #3 both return iterators since the lvalue vec and specializations of subrange model borrowed_range.
— end example]
For a type R that models range:
  • if R models borrowed_range, then borrowed_iterator_t<R> denotes iterator_t<R>, and borrowed_subrange_t<R> denotes subrange<iterator_t<R>>;
  • otherwise, both borrowed_iterator_t<R> and borrowed_subrange_t<R> denote dangling.