Difference between revisions of "cpp/ranges/dangling"
From cppreference.com
(P1252R2 dangling) |
(models->model) |
||
(9 intermediate revisions by 4 users not shown) | |||
Line 9: | Line 9: | ||
{{dcl end}} | {{dcl end}} | ||
− | {{tt|dangling}} is a placeholder type and an empty class type, used together with the template aliases {{ltt|cpp/ranges/ | + | {{tt|dangling}} is a placeholder type and an empty class type, used together with the template aliases {{ltt|cpp/ranges/borrowed_iterator_t|ranges::borrowed_iterator_t}} and {{ltt|cpp/ranges/borrowed_iterator_t|ranges::borrowed_subrange_t}}. |
− | When some [[cpp/algorithm/ranges| | + | When some [[cpp/algorithm/ranges|constrained algorithms]] that usually return an iterator or a subrange of a {{lconcept|range}} take a particular rvalue {{tt|range}} argument that does not model {{lconcept|borrowed_range}}, {{tt|dangling}} will be returned instead to avoid returning potentially dangling results. |
===Member functions=== | ===Member functions=== | ||
Line 27: | Line 27: | ||
@1@ {{tt|dangling}} is trivially default constructible. | @1@ {{tt|dangling}} is trivially default constructible. | ||
@2@ {{tt|dangling}} can be constructed from arguments of arbitrary number and arbitrary non-void type. The construction does not have any side-effect itself. | @2@ {{tt|dangling}} can be constructed from arguments of arbitrary number and arbitrary non-void type. The construction does not have any side-effect itself. | ||
− | In other words, after replacing the type (e.g. an iterator type) in | + | In other words, after replacing the type (e.g. an iterator type) in a well-formed non-aggregate initialization with {{tt|dangling}}, the resulting initialization is also well-formed. |
}} | }} | ||
===Example=== | ===Example=== | ||
− | {{example}} | + | {{example|code= |
+ | #include <algorithm> | ||
+ | #include <array> | ||
+ | #include <iostream> | ||
+ | #include <ranges> | ||
+ | #include <type_traits> | ||
+ | #include <string_view> | ||
+ | |||
+ | int main() | ||
+ | { | ||
+ | auto get_array_by_value = [] { return std::array{0, 1, 0, 1}; }; | ||
+ | auto dangling_iter = std::ranges::max_element(get_array_by_value()); | ||
+ | static_assert(std::is_same_v<std::ranges::dangling, decltype(dangling_iter)>); | ||
+ | // std::cout << *dangling_iter << '\n'; // compilation error: no match for 'operator*' | ||
+ | // (operand type is 'std::ranges::dangling') | ||
+ | |||
+ | auto get_persistent_array = []() -> const std::array<int, 4>& { | ||
+ | static constexpr std::array a{0, 1, 0, 1}; | ||
+ | return a; | ||
+ | }; | ||
+ | auto valid_iter = std::ranges::max_element(get_persistent_array()); | ||
+ | static_assert(!std::is_same_v<std::ranges::dangling, decltype(valid_iter)>); | ||
+ | std::cout << *valid_iter << ' '; // 1 | ||
+ | |||
+ | |||
+ | auto get_string_view = [] { return std::string_view{"alpha"}; }; | ||
+ | auto valid_iter2 = std::ranges::min_element(get_string_view()); | ||
+ | // OK: std::basic_string_view models borrowed_range | ||
+ | static_assert(!std::is_same_v<std::ranges::dangling, decltype(valid_iter2)>); | ||
+ | std::cout << '\'' << *valid_iter2 << '\'' << '\n'; // 'a' | ||
+ | } | ||
+ | | output=1 'a' | ||
+ | }} | ||
===See also=== | ===See also=== | ||
{{dsc begin}} | {{dsc begin}} | ||
− | {{dsc inc | cpp/ranges/dsc | + | {{dsc inc | cpp/ranges/dsc borrowed_iterator_t}} |
+ | {{dsc inc | cpp/ranges/dsc borrowed_range}} | ||
{{dsc end}} | {{dsc end}} | ||
− | {{langlinks|ja|zh}} | + | {{langlinks|es|ja|ru|zh}} |
Latest revision as of 17:20, 18 September 2021
Defined in header <ranges>
|
||
struct dangling; |
(since C++20) | |
dangling
is a placeholder type and an empty class type, used together with the template aliases ranges::borrowed_iterator_t and ranges::borrowed_subrange_t.
When some constrained algorithms that usually return an iterator or a subrange of a range
take a particular rvalue range
argument that does not model borrowed_range
, dangling
will be returned instead to avoid returning potentially dangling results.
Contents |
[edit] Member functions
std::ranges::dangling::dangling
constexpr dangling() noexcept = default; |
(1) | |
template<class... Args> constexpr dangling(Args&&...) noexcept { } |
(2) | |
1)
dangling
is trivially default constructible.2)
dangling
can be constructed from arguments of arbitrary number and arbitrary non-void type. The construction does not have any side-effect itself.
In other words, after replacing the type (e.g. an iterator type) in a well-formed non-aggregate initialization with dangling
, the resulting initialization is also well-formed.
[edit] Example
Run this code
#include <algorithm> #include <array> #include <iostream> #include <ranges> #include <type_traits> #include <string_view> int main() { auto get_array_by_value = [] { return std::array{0, 1, 0, 1}; }; auto dangling_iter = std::ranges::max_element(get_array_by_value()); static_assert(std::is_same_v<std::ranges::dangling, decltype(dangling_iter)>); // std::cout << *dangling_iter << '\n'; // compilation error: no match for 'operator*' // (operand type is 'std::ranges::dangling') auto get_persistent_array = []() -> const std::array<int, 4>& { static constexpr std::array a{0, 1, 0, 1}; return a; }; auto valid_iter = std::ranges::max_element(get_persistent_array()); static_assert(!std::is_same_v<std::ranges::dangling, decltype(valid_iter)>); std::cout << *valid_iter << ' '; // 1 auto get_string_view = [] { return std::string_view{"alpha"}; }; auto valid_iter2 = std::ranges::min_element(get_string_view()); // OK: std::basic_string_view models borrowed_range static_assert(!std::is_same_v<std::ranges::dangling, decltype(valid_iter2)>); std::cout << '\'' << *valid_iter2 << '\'' << '\n'; // 'a' }
Output:
1 'a'
[edit] See also
obtains iterator type or subrange type of a borrowed_range (alias template) | |
(C++20) |
specifies that a type is a range and iterators obtained from an expression of it can be safely returned without danger of dangling (concept) |