24 Ranges library [ranges]

24.5 Range utilities [range.utility]

24.5.5 Dangling iterator handling [range.dangling]

The tag 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 tag type dangling is returned instead of an iterator or subrange.
namespace std::ranges { struct dangling { constexpr dangling() noexcept = default; template<class... Args> constexpr dangling(Args&&...) 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(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.