Difference between revisions of "cpp/iterator/unreachable sentinel t"
From cppreference.com
(unreachable_sentinel) |
m (tt) |
||
(5 intermediate revisions by 3 users not shown) | |||
Line 3: | Line 3: | ||
{{dcl begin}} | {{dcl begin}} | ||
− | {{dcl header | iterator}} | + | {{dcl header|iterator}} |
− | {{dcl | num=1 | since=c++20 | | + | {{dcl|num=1|since=c++20| |
struct unreachable_sentinel_t; | struct unreachable_sentinel_t; | ||
}} | }} | ||
− | {{dcl | num=2 | since=c++20 | | + | {{dcl|num=2|since=c++20| |
inline constexpr unreachable_sentinel_t unreachable_sentinel{}; | inline constexpr unreachable_sentinel_t unreachable_sentinel{}; | ||
}} | }} | ||
Line 17: | Line 17: | ||
===Non-member functions=== | ===Non-member functions=== | ||
{{dsc begin}} | {{dsc begin}} | ||
− | {{dsc tfun | cpp/iterator/unreachable_sentinel_t | inlinemem=true | title=operator== | | + | {{dsc tfun|cpp/iterator/unreachable_sentinel_t|inlinemem=true|title=operator==|compares an {{tt|unreachable_sentinel_t}} with a value of any {{lconcept|weakly_incrementable}} type|notes={{mark c++20}}}} |
{{dsc end}} | {{dsc end}} | ||
− | {{member | operator{{==}} | + | {{member|operator{{==}}{{small|(std::unreachable_sentinel_t)}}| |
− | {{ddcl | since=c++20 | 1= | + | {{ddcl|since=c++20|1= |
template<std::weakly_incrementable I> | template<std::weakly_incrementable I> | ||
− | friend constexpr operator==( unreachable_sentinel_t, const I& ) noexcept | + | friend constexpr bool operator==( unreachable_sentinel_t, const I& ) noexcept |
{ return false; } | { return false; } | ||
}} | }} | ||
Line 29: | Line 29: | ||
{{tt|unreachable_sentinel_t}} can be compared with any {{lconcept|weakly_incrementable}} type and the result is always {{c|false}}. | {{tt|unreachable_sentinel_t}} can be compared with any {{lconcept|weakly_incrementable}} type and the result is always {{c|false}}. | ||
− | {{cpp/hidden friend|tmpl=yes|std::unreachable_sentinel_t}} | + | {{cpp/hidden friend|tmpl=yes|{{tt|std::unreachable_sentinel_t}}}} |
}} | }} | ||
===Example=== | ===Example=== | ||
− | {{example|code= | + | {{example |
− | + | |code= | |
− | + | ||
#include <algorithm> | #include <algorithm> | ||
+ | #include <cstddef> | ||
#include <iostream> | #include <iostream> | ||
+ | #include <iterator> | ||
template<class CharT> | template<class CharT> | ||
− | std::size_t | + | constexpr std::size_t strlen(const CharT* s) |
{ | { | ||
return std::ranges::find(s, std::unreachable_sentinel, CharT{}) - s; | return std::ranges::find(s, std::unreachable_sentinel, CharT{}) - s; | ||
+ | } | ||
+ | |||
+ | template<class CharT> | ||
+ | constexpr std::size_t find_first(const CharT* haystack, const CharT* needle) | ||
+ | { | ||
+ | const char* needle_end = needle + strlen(needle); | ||
+ | // search(begin, unreachable_sentinel) is usually more efficient than | ||
+ | // search(begin, end) due to one less comparison per cycle. | ||
+ | // But "needle" MUST BE PRESENT in the "haystack", otherwise the call | ||
+ | // is UB (which is a compile-time error in constexpr context). | ||
+ | auto found = std::ranges::search(haystack, std::unreachable_sentinel, | ||
+ | needle, needle_end); | ||
+ | return found.begin() - haystack; | ||
} | } | ||
int main() | int main() | ||
{ | { | ||
− | + | static_assert(strlen("The quick brown fox jumps over a lazy dog.") == 42); | |
− | + | static_assert(find_first("unsigned short int", "short") == 9); | |
+ | // static_assert(find_first("long int", "float")); // compile-time error | ||
} | } | ||
− | |||
− | |||
}} | }} | ||
===See also=== | ===See also=== | ||
{{dsc begin}} | {{dsc begin}} | ||
− | {{dsc inc | cpp/ranges/dsc iota_view}} | + | {{dsc inc|cpp/ranges/dsc iota_view}} |
{{dsc end}} | {{dsc end}} | ||
{{langlinks|ja|zh}} | {{langlinks|ja|zh}} |
Latest revision as of 03:55, 17 July 2024
Defined in header <iterator>
|
||
struct unreachable_sentinel_t; |
(1) | (since C++20) |
inline constexpr unreachable_sentinel_t unreachable_sentinel{}; |
(2) | (since C++20) |
1)
unreachable_sentinel_t
is an empty class type that can be used to denote the “upper bound” of an unbounded interval.2)
unreachable_sentinel
is a constant of type unreachable_sentinel_t
.Contents |
[edit] Non-member functions
operator== (C++20) |
compares an unreachable_sentinel_t with a value of any weakly_incrementable type (function template) |
operator==(std::unreachable_sentinel_t)
template<std::weakly_incrementable I> friend constexpr bool operator==( unreachable_sentinel_t, const I& ) noexcept |
(since C++20) | |
unreachable_sentinel_t
can be compared with any weakly_incrementable
type and the result is always false.
This function template is not visible to ordinary unqualified or qualified lookup, and can only be found by argument-dependent lookup when std::unreachable_sentinel_t
is an associated class of the arguments.
[edit] Example
Run this code
#include <algorithm> #include <cstddef> #include <iostream> #include <iterator> template<class CharT> constexpr std::size_t strlen(const CharT* s) { return std::ranges::find(s, std::unreachable_sentinel, CharT{}) - s; } template<class CharT> constexpr std::size_t find_first(const CharT* haystack, const CharT* needle) { const char* needle_end = needle + strlen(needle); // search(begin, unreachable_sentinel) is usually more efficient than // search(begin, end) due to one less comparison per cycle. // But "needle" MUST BE PRESENT in the "haystack", otherwise the call // is UB (which is a compile-time error in constexpr context). auto found = std::ranges::search(haystack, std::unreachable_sentinel, needle, needle_end); return found.begin() - haystack; } int main() { static_assert(strlen("The quick brown fox jumps over a lazy dog.") == 42); static_assert(find_first("unsigned short int", "short") == 9); // static_assert(find_first("long int", "float")); // compile-time error }
[edit] See also
(C++20) |
a view consisting of a sequence generated by repeatedly incrementing an initial value(class template) (customization point object) |