Difference between revisions of "cpp/algorithm/ranges/starts with"
m (→Notes: ~FTM; fmt) |
m (→Synopsis: fmt.) |
||
(One intermediate revision by one user not shown) | |||
Line 10: | Line 10: | ||
class Proj1 = std::identity, class Proj2 = std::identity > | class Proj1 = std::identity, class Proj2 = std::identity > | ||
requires std::indirectly_comparable<I1, I2, Pred, Proj1, Proj2> | requires std::indirectly_comparable<I1, I2, Pred, Proj1, Proj2> | ||
− | constexpr bool starts_with( I1 first1, S1 last1, I2 first2, S2 last2, | + | constexpr bool |
− | + | starts_with( I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, | |
+ | Proj1 proj1 = {}, Proj2 proj2 = {} ); | ||
}} | }} | ||
{{dcl|num=2|since=c++23|1= | {{dcl|num=2|since=c++23|1= | ||
Line 20: | Line 21: | ||
ranges::iterator_t<R2>, | ranges::iterator_t<R2>, | ||
Pred, Proj1, Proj2> | Pred, Proj1, Proj2> | ||
− | constexpr bool starts_with( R1&& r1, R2&& r2, | + | constexpr bool |
− | + | starts_with( R1&& r1, R2&& r2, Pred pred = {}, | |
+ | Proj1 proj1 = {}, Proj2 proj2 = {} ); | ||
}} | }} | ||
{{dcl end}} | {{dcl end}} | ||
Line 27: | Line 29: | ||
Checks whether the second range matches the prefix of the first range. | Checks whether the second range matches the prefix of the first range. | ||
− | @1@ Let {{tt|N1}} and {{tt|N2}} denote the size of ranges {{ | + | @1@ Let {{tt|N1}} and {{tt|N2}} denote the size of ranges {{range|first1|last1}} and {{range|first2|last2}} respectively. If {{c|N1 < N2}}, returns {{c|false}}. Otherwise, returns {{c|true}} only if every element in the range {{range|first2|last2}} is equal to the corresponding element in {{range|first1|first1 + N2}}. Comparison is done by applying the binary predicate {{c|pred}} to elements in two ranges projected by {{c|proj1}} and {{c|proj2}} respectively. |
− | @2@ Same as {{v|1}}, but uses {{ | + | @2@ Same as {{v|1}}, but uses {{c|r1}} and {{c|r2}} as the source ranges, as if using {{c|ranges::begin(r1)}} as {{c|first1}}, {{c|ranges:begin(r2)}} as {{c|first2}}, {{c|ranges::end(r1)}} as {{c|last1}}, and {{c|ranges::end(r2)}} as {{c|last2}}. |
{{cpp/ranges/niebloid}} | {{cpp/ranges/niebloid}} | ||
Line 48: | Line 50: | ||
===Complexity=== | ===Complexity=== | ||
− | Linear: at most {{ | + | Linear: at most {{c|min(N1, N2)}} applications of the predicate and both projections. |
===Possible implementation=== | ===Possible implementation=== | ||
Line 58: | Line 60: | ||
class Pred = ranges::equal_to, | class Pred = ranges::equal_to, | ||
class Proj1 = std::identity, class Proj2 = std::identity> | class Proj1 = std::identity, class Proj2 = std::identity> | ||
− | + | requires std::indirectly_comparable<I1, I2, Pred, Proj1, Proj2> | |
constexpr bool operator()(I1 first1, S1 last1, I2 first2, S2 last2, | constexpr bool operator()(I1 first1, S1 last1, I2 first2, S2 last2, | ||
Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const | Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const | ||
Line 70: | Line 72: | ||
class Pred = ranges::equal_to, | class Pred = ranges::equal_to, | ||
class Proj1 = std::identity, class Proj2 = std::identity> | class Proj1 = std::identity, class Proj2 = std::identity> | ||
− | + | requires std::indirectly_comparable<ranges::iterator_t<R1>, | |
− | + | ranges::iterator_t<R2>, | |
− | + | Pred, Proj1, Proj2> | |
constexpr bool operator()(R1&& r1, R2&& r2, | constexpr bool operator()(R1&& r1, R2&& r2, | ||
Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const | Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const | ||
Line 82: | Line 84: | ||
}; | }; | ||
− | inline constexpr starts_with_fn starts_with{}; | + | inline constexpr starts_with_fn starts_with {}; |
}} | }} | ||
Line 90: | Line 92: | ||
===Example=== | ===Example=== | ||
{{example|code= | {{example|code= | ||
− | |||
#include <algorithm> | #include <algorithm> | ||
#include <iostream> | #include <iostream> | ||
#include <ranges> | #include <ranges> | ||
+ | #include <string_view> | ||
int main() | int main() | ||
Line 125: | Line 127: | ||
constexpr static auto v = { 1, 3, 5, 7, 9 }; | constexpr static auto v = { 1, 3, 5, 7, 9 }; | ||
constexpr auto odd = [](int x) { return x % 2; }; | constexpr auto odd = [](int x) { return x % 2; }; | ||
− | static_assert( std::ranges::starts_with( v, std::views::iota(1) | + | static_assert(std::ranges::starts_with(v, std::views::iota(1) |
− | + | {{!}} std::views::filter(odd) | |
− | + | {{!}} std::views::take(3))); | |
} | } | ||
|output=true false true false | |output=true false true false |
Latest revision as of 11:42, 23 April 2024
Defined in header <algorithm>
|
||
Call signature |
||
template< std::input_iterator I1, std::sentinel_for<I1> S1, std::input_iterator I2, std::sentinel_for<I2> S2, |
(1) | (since C++23) |
template< ranges::input_range R1, ranges::input_range R2, class Pred = ranges::equal_to, |
(2) | (since C++23) |
Checks whether the second range matches the prefix of the first range.
N1
and N2
denote the size of ranges [
first1,
last1)
and [
first2,
last2)
respectively. If N1 < N2, returns false. Otherwise, returns true only if every element in the range [
first2,
last2)
is equal to the corresponding element in [
first1,
first1 + N2)
. Comparison is done by applying the binary predicate pred to elements in two ranges projected by proj1 and proj2 respectively.The function-like entities described on this page are niebloids, that is:
- Explicit template argument lists cannot be specified when calling any of them.
- None of them are visible to argument-dependent lookup.
- When any of them are found by normal unqualified lookup as the name to the left of the function-call operator, argument-dependent lookup is inhibited.
In practice, they may be implemented as function objects, or with special compiler extensions.
Contents |
[edit] Parameters
first1, last1 | - | the range of elements to examine |
r1 | - | the range of elements to examine |
first2, last2 | - | the range of elements to be used as the prefix |
r2 | - | the range of elements to be used as the prefix |
pred | - | the binary predicate that compares the projected elements |
proj1 | - | the projection to apply to the elements of the range to examine |
proj2 | - | the projection to apply to the elements of the range to be used as the prefix |
[edit] Return value
true if the second range matches the prefix of the first range, false otherwise.
[edit] Complexity
Linear: at most min(N1, N2) applications of the predicate and both projections.
[edit] Possible implementation
struct starts_with_fn { template<std::input_iterator I1, std::sentinel_for<I1> S1, std::input_iterator I2, std::sentinel_for<I2> S2, class Pred = ranges::equal_to, class Proj1 = std::identity, class Proj2 = std::identity> requires std::indirectly_comparable<I1, I2, Pred, Proj1, Proj2> constexpr bool operator()(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const { return ranges::mismatch(std::move(first1), last1, std::move(first2), last2, std::move(pred), std::move(proj1), std::move(proj2) ).in2 == last2; } template<ranges::input_range R1, ranges::input_range R2, class Pred = ranges::equal_to, class Proj1 = std::identity, class Proj2 = std::identity> requires std::indirectly_comparable<ranges::iterator_t<R1>, ranges::iterator_t<R2>, Pred, Proj1, Proj2> constexpr bool operator()(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const { return (*this)(ranges::begin(r1), ranges::end(r1), ranges::begin(r2), ranges::end(r2), std::move(pred), std::move(proj1), std::move(proj2)); } }; inline constexpr starts_with_fn starts_with {}; |
[edit] Notes
Feature-test macro | Value | Std | Feature |
---|---|---|---|
__cpp_lib_ranges_starts_ends_with |
202106L | (C++23) | std::ranges::starts_with , std::ranges::ends_with
|
[edit] Example
#include <algorithm> #include <iostream> #include <ranges> #include <string_view> int main() { using namespace std::literals; constexpr auto ascii_upper = [](char8_t c) { return u8'a' <= c && c <= u8'z' ? static_cast<char8_t>(c + u8'A' - u8'a') : c; }; constexpr auto cmp_ignore_case = [=](char8_t x, char8_t y) { return ascii_upper(x) == ascii_upper(y); }; static_assert(std::ranges::starts_with("const_cast", "const"sv)); static_assert(std::ranges::starts_with("constexpr", "const"sv)); static_assert(!std::ranges::starts_with("volatile", "const"sv)); std::cout << std::boolalpha << std::ranges::starts_with(u8"Constantinopolis", u8"constant"sv, {}, ascii_upper, ascii_upper) << ' ' << std::ranges::starts_with(u8"Istanbul", u8"constant"sv, {}, ascii_upper, ascii_upper) << ' ' << std::ranges::starts_with(u8"Metropolis", u8"metro"sv, cmp_ignore_case) << ' ' << std::ranges::starts_with(u8"Acropolis", u8"metro"sv, cmp_ignore_case) << '\n'; constexpr static auto v = { 1, 3, 5, 7, 9 }; constexpr auto odd = [](int x) { return x % 2; }; static_assert(std::ranges::starts_with(v, std::views::iota(1) | std::views::filter(odd) | std::views::take(3))); }
Output:
true false true false
[edit] See also
(C++23) |
checks whether a range ends with another range (niebloid) |
(C++20) |
finds the first position where two ranges differ (niebloid) |
(C++20) |
checks if the string starts with the given prefix (public member function of std::basic_string<CharT,Traits,Allocator> )
|
(C++20) |
checks if the string view starts with the given prefix (public member function of std::basic_string_view<CharT,Traits> )
|