std::ranges::starts_with(3)
π NAME π
okay so bestie, this is the std::ranges::starts_with(3) page from the C++ Standard Libary (yes, the header literally spells it βLibaryβ β iconic, no notes). The thing itself is std::ranges::starts_with β yes, name so nice it said it twice: std::ranges::starts_with - std::ranges::starts_with. Itβs the βdoes range two match the beginning of range one?β girly. periodt. π
β¨ Synopsis β¨
Defined in header <algorithm> β call signature incoming β¨
Defined in header <algorithm>
Call signature
Overload (1) β since C++23 π
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, Pred pred = {},
Proj1 proj1 = {}, Proj2 proj2 = {} );
Overload (2) β since C++23 π¦
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, Pred pred = {},
Proj1 proj1 = {}, Proj2 proj2 = {} );
So what does it do? Checks whether the second range matches the prefix of the first range. Thatβs the whole vibe check. π«Ά
- Let
N1andN2denote the size of ranges[first1, last1)and[first2, last2)respectively. IfN1 < N2, returnsfalse. Otherwise, returnstrueonly 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 predicatepredto elements in two ranges projected byproj1andproj2respectively. - Same as (1), but uses
r1andr2as the source ranges, as if usingranges::begin(r1)asfirst1,ranges:begin(r2)asfirst2,ranges::end(r1)aslast1, andranges::end(r2)aslast2.
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. lowkey important, bestie π
πΈ 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 πͺ
π Return value π
true if the second range matches the prefix of the first range, false otherwise. thatβs it. thatβs the answer. β¨
π¦ Complexity π¦
Linear: at most min(N1, N2) applications of the predicate and both projections. no secret extra chaos, we love a clean bound. π
π Possible implementation π
hereβs what a possible implementation looks like β itβs giving function-object realness:
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 {};
π§ Notes π§
Feature-test macro check π΅οΈββοΈ β yes, thereβs a macro for this:
- Feature-test macro:
__cpp_lib_ranges_starts_ends_with - Value:
202106L - Std:
(C++23) - Feature:
std::ranges::starts_with, std::ranges::ends_with
π Example π
// Run this code
#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
π See also π
ranges::ends_withβ checks whether a range ends with another range (C++23) (niebloid)ranges::mismatchβ finds the first position where two ranges differ (C++20) (niebloid)starts_withβ checks if the string starts with the given prefix (C++20) (public member function ofstd::basic_string<CharT,Traits,Allocator>)starts_withβ checks if the string view starts with the given prefix (C++20) (public member function ofstd::basic_string_view<CharT,Traits>)
mwah π this page says it came from http://cppreference.com, dated 2024.06.10, and the page is std::ranges::starts_with(3). bye bestie π«Ά
π¦ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms