Difference between revisions of "cpp/algorithm/ranges/starts with"
m (→Example: rm extras.) |
m (→Synopsis: fmt.) |
||
(7 intermediate revisions by 3 users not shown) | |||
Line 2: | Line 2: | ||
{{cpp/algorithm/ranges/navbar}} | {{cpp/algorithm/ranges/navbar}} | ||
{{dcl begin}} | {{dcl begin}} | ||
− | {{dcl header | algorithm}} | + | {{dcl header|algorithm}} |
{{dcl h|Call signature}} | {{dcl h|Call signature}} | ||
− | {{dcl | num=1 | since=c++23 |1= | + | {{dcl|num=1|since=c++23|1= |
− | template<std::input_iterator I1, std::sentinel_for<I1> S1, | + | 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 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= |
− | template<ranges::input_range R1, ranges::input_range R2, | + | 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 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 35: | Line 37: | ||
===Parameters=== | ===Parameters=== | ||
{{par begin}} | {{par begin}} | ||
− | {{par | first1, last1 | the range of elements to examine}} | + | {{par|first1, last1|the range of elements to examine}} |
− | {{par | r1 | the range of elements to examine}} | + | {{par|r1|the range of elements to examine}} |
− | {{par | first2, last2 | the range of elements to be used as the prefix}} | + | {{par|first2, last2|the range of elements to be used as the prefix}} |
− | {{par | r2 | the range of elements to be used as the prefix}} | + | {{par|r2|the range of elements to be used as the prefix}} |
− | {{par | pred | the binary predicate that compares the projected elements}} | + | {{par|pred|the binary predicate that compares the projected elements}} |
− | {{par | proj1 | the projection to apply to the elements of the range to examine}} | + | {{par|proj1|the projection to apply to the elements of the range to examine}} |
− | {{par | proj2 | the projection to apply to the elements of the range to be used as the prefix}} | + | {{par|proj2|the projection to apply to the elements of the range to be used as the prefix}} |
{{par end}} | {{par end}} | ||
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=== | ||
{{eq fun|1= | {{eq fun|1= | ||
− | struct starts_with_fn { | + | 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> | 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, | + | { |
− | + | 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>, | requires std::indirectly_comparable<ranges::iterator_t<R1>, | ||
ranges::iterator_t<R2>, | ranges::iterator_t<R2>, | ||
Pred, Proj1, Proj2> | 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), | + | { |
− | + | 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{}; | + | inline constexpr starts_with_fn starts_with {}; |
}} | }} | ||
+ | |||
+ | ===Notes=== | ||
+ | {{feature test macro|__cpp_lib_ranges_starts_ends_with|std=C++23|value=202106L|{{tt|std::ranges::starts_with}}, {{lc|std::ranges::ends_with}}}} | ||
===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 96: | Line 104: | ||
{ | { | ||
return u8'a' <= c && c <= u8'z' ? static_cast<char8_t>(c + u8'A' - u8'a') : 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); | ||
}; | }; | ||
Line 102: | Line 115: | ||
static_assert(!std::ranges::starts_with("volatile", "const"sv)); | static_assert(!std::ranges::starts_with("volatile", "const"sv)); | ||
− | std::cout | + | 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 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= | + | |output=true false true false |
− | true | + | |
− | false | + | |
}} | }} | ||
===See also=== | ===See also=== | ||
{{dsc begin}} | {{dsc begin}} | ||
− | {{dsc inc | cpp/algorithm/ranges/dsc ends_with}} | + | {{dsc inc|cpp/algorithm/ranges/dsc ends_with}} |
− | {{dsc inc | cpp/algorithm/ranges/dsc mismatch}} | + | {{dsc inc|cpp/algorithm/ranges/dsc mismatch}} |
− | {{dsc inc | cpp/string/basic_string/dsc starts_with}} | + | {{dsc inc|cpp/string/basic_string/dsc starts_with}} |
− | {{dsc inc | cpp/string/basic_string_view/dsc starts_with}} | + | {{dsc inc|cpp/string/basic_string_view/dsc starts_with}} |
{{dsc end}} | {{dsc end}} | ||
{{langlinks|es|ja|ru|zh}} | {{langlinks|es|ja|ru|zh}} |
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> )
|