Difference between revisions of "cpp/ranges/begin"
m (E: ~) |
D41D8CD98F (Talk | contribs) (also available when <iterator> is included ([range.access.general]/1)) |
||
(9 intermediate revisions by 6 users not shown) | |||
Line 1: | Line 1: | ||
− | {{cpp/ranges/title | begin}} | + | {{cpp/ranges/title|begin}} |
{{cpp/ranges/navbar}} | {{cpp/ranges/navbar}} | ||
− | |||
{{dcl begin}} | {{dcl begin}} | ||
− | {{dcl header | ranges}} | + | {{dcl header|ranges}} |
− | {{dcl | notes={{mark custpt}} | since=c++20 | 1= | + | {{dcl header|iterator}} |
− | inline namespace /*unspecified*/ { | + | {{dcl|notes={{mark custpt}}|since=c++20|1= |
− | inline constexpr /*unspecified*/ begin = /*unspecified*/; | + | inline namespace /* unspecified */ { |
+ | inline constexpr /* unspecified */ begin = /* unspecified */; | ||
} | } | ||
}} | }} | ||
{{dcl h|Call signature}} | {{dcl h|Call signature}} | ||
− | {{dcl|1= | + | {{dcl|since=c++20|1= |
template< class T > | template< class T > | ||
requires /* see below */ | requires /* see below */ | ||
− | constexpr std::input_or_output_iterator auto begin(T&& t); | + | constexpr std::input_or_output_iterator auto begin( T&& t ); |
}} | }} | ||
{{dcl end}} | {{dcl end}} | ||
Line 21: | Line 21: | ||
{{image|range-begin-end.svg}} | {{image|range-begin-end.svg}} | ||
− | + | If the argument is an lvalue or {{c|ranges::enable_borrowed_range<std::remove_cv_t<T>>}} is {{c|true}}, then a call to {{tt|ranges::begin}} is [[cpp/language/expressions#Expression-equivalence|expression-equivalent]] to: | |
− | # {{c|t + 0}} if {{ | + | # {{c|t + 0}} if {{c|t}} has an array type. |
− | # | + | #* If {{c/core|std::remove_all_extents_t<std::remove_reference_t<T>>}} is incomplete, then the call to {{tt|ranges::begin}} is ill-formed, no diagnostic required. |
− | # Otherwise, {{c| | + | # Otherwise, {{rev inl|until=c++23|{{box|{{lti|cpp/standard library/decay-copy}}{{c/core|(t.begin())}}}}}}{{rev inl|since=c++23|{{c|auto(t.begin())}}}}, if that expression is valid and its type models {{lc|std::input_or_output_iterator}}. |
− | # Otherwise, {{c|begin( | + | # Otherwise, {{rev inl|until=c++23|{{box|{{lti|cpp/standard library/decay-copy}}{{c/core|(begin(t))}}}}}}{{rev inl|since=c++23|{{c|auto(begin(t))}}}}, if {{tt|T}} is a class or enumeration type, that expression is valid and its type models {{lc|std::input_or_output_iterator}}, where the meaning of {{tt|begin}} is established as if by performing [[cpp/language/adl|argument-dependent lookup]] only. |
− | + | ||
− | + | ||
− | + | ||
− | In all other cases, a call to {{tt|ranges::begin}} is ill-formed, which can result in [[cpp/language/sfinae|substitution failure]] when | + | In all other cases, a call to {{tt|ranges::begin}} is ill-formed, which can result in [[cpp/language/sfinae|substitution failure]] when the call appears in the immediate context of a template instantiation. |
− | |||
{{cpp/ranges/cpo}} | {{cpp/ranges/cpo}} | ||
Line 38: | Line 34: | ||
If the argument is an rvalue (i.e. {{tt|T}} is an object type) and {{c|ranges::enable_borrowed_range<std::remove_cv_t<T>>}} is {{c|false}}, the call to {{tt|ranges::begin}} is ill-formed, which also results in substitution failure. | If the argument is an rvalue (i.e. {{tt|T}} is an object type) and {{c|ranges::enable_borrowed_range<std::remove_cv_t<T>>}} is {{c|false}}, the call to {{tt|ranges::begin}} is ill-formed, which also results in substitution failure. | ||
− | The return type models {{ | + | The return type models {{lc|std::input_or_output_iterator}} in all cases. |
+ | {{cpp/ranges/prv}} | ||
===Example=== | ===Example=== | ||
{{example | {{example | ||
− | + | |code= | |
− | + | #include <cassert> | |
+ | #include <ranges> | ||
#include <vector> | #include <vector> | ||
− | + | ||
− | + | ||
int main() | int main() | ||
{ | { | ||
− | std::vector | + | std::vector v{3, 1, 4}; |
auto vi = std::ranges::begin(v); | auto vi = std::ranges::begin(v); | ||
− | std:: | + | auto vci = std::ranges::cbegin(v); |
− | *vi = 42; // OK | + | assert(*vi == 3 and *vi == *vci); |
+ | ++vi; | ||
+ | ++vci; // OK: vci is modifiable object | ||
+ | *vi = 42; // OK: vi points to mutable element | ||
+ | // *vci = 13; // Error: vci points to immutable element | ||
− | int a[] | + | int a[]{-5, 10, 15}; |
− | auto ai = std::ranges::begin(a); | + | auto ai = std::ranges::begin(a); // works with C-arrays as well |
− | + | assert(*ai == -5); | |
*ai = 42; // OK | *ai = 42; // OK | ||
} | } | ||
− | |||
− | |||
− | |||
}} | }} | ||
+ | |||
+ | ===Defect reports=== | ||
+ | {{dr list begin}} | ||
+ | {{dr list item|paper=P2602R2|std=C++20|before=there's machinery to prohibit certain non-member {{tt|begin}} found by [[cpp/language/adl|ADL]]|after=removed such machinery}} | ||
+ | {{dr list end}} | ||
===See also=== | ===See also=== | ||
{{dsc begin}} | {{dsc begin}} | ||
− | {{dsc inc | cpp/ranges/dsc cbegin}} | + | {{dsc inc|cpp/ranges/dsc cbegin}} |
− | {{dsc inc | cpp/iterator/dsc begin}} | + | {{dsc inc|cpp/iterator/dsc begin}} |
{{dsc end}} | {{dsc end}} | ||
− | {{langlinks|es|ja|zh}} | + | {{langlinks|de|es|ja|ru|zh}} |
Latest revision as of 09:28, 8 September 2023
Defined in header <ranges>
|
||
Defined in header <iterator>
|
||
inline namespace /* unspecified */ { inline constexpr /* unspecified */ begin = /* unspecified */; |
(since C++20) (customization point object) |
|
Call signature |
||
template< class T > requires /* see below */ |
(since C++20) | |
Returns an iterator to the first element of the argument.
If the argument is an lvalue or ranges::enable_borrowed_range<std::remove_cv_t<T>> is true, then a call to ranges::begin
is expression-equivalent to:
- t + 0 if t has an array type.
- If std::remove_all_extents_t<std::remove_reference_t<T>> is incomplete, then the call to
ranges::begin
is ill-formed, no diagnostic required.
- If std::remove_all_extents_t<std::remove_reference_t<T>> is incomplete, then the call to
- Otherwise, decay-copy(t.begin())(until C++23)auto(t.begin())(since C++23), if that expression is valid and its type models std::input_or_output_iterator.
- Otherwise, decay-copy(begin(t))(until C++23)auto(begin(t))(since C++23), if
T
is a class or enumeration type, that expression is valid and its type models std::input_or_output_iterator, where the meaning ofbegin
is established as if by performing argument-dependent lookup only.
In all other cases, a call to ranges::begin
is ill-formed, which can result in substitution failure when the call appears in the immediate context of a template instantiation.
Contents |
Customization point objects
The name ranges::begin
denotes a customization point object, which is a const function object of a literal semiregular
class type. For exposition purposes, the cv-unqualified version of its type is denoted as __begin_fn
.
All instances of __begin_fn
are equal. The effects of invoking different instances of type __begin_fn
on the same arguments are equivalent, regardless of whether the expression denoting the instance is an lvalue or rvalue, and is const-qualified or not (however, a volatile-qualified instance is not required to be invocable). Thus, ranges::begin
can be copied freely and its copies can be used interchangeably.
Given a set of types Args...
, if std::declval<Args>()... meet the requirements for arguments to ranges::begin
above, __begin_fn
models
- std::invocable<__begin_fn, Args...>,
- std::invocable<const __begin_fn, Args...>,
- std::invocable<__begin_fn&, Args...>, and
- std::invocable<const __begin_fn&, Args...>.
Otherwise, no function call operator of __begin_fn
participates in overload resolution.
[edit] Notes
If the argument is an rvalue (i.e. T
is an object type) and ranges::enable_borrowed_range<std::remove_cv_t<T>> is false, the call to ranges::begin
is ill-formed, which also results in substitution failure.
The return type models std::input_or_output_iterator in all cases.
The C++20 standard requires that if the underlying begin
function call returns a prvalue, the return value is move-constructed from the materialized temporary object. All implementations directly return the prvalue instead. The requirement is corrected by the post-C++20 proposal P0849R8 to match the implementations.
[edit] Example
#include <cassert> #include <ranges> #include <vector> int main() { std::vector v{3, 1, 4}; auto vi = std::ranges::begin(v); auto vci = std::ranges::cbegin(v); assert(*vi == 3 and *vi == *vci); ++vi; ++vci; // OK: vci is modifiable object *vi = 42; // OK: vi points to mutable element // *vci = 13; // Error: vci points to immutable element int a[]{-5, 10, 15}; auto ai = std::ranges::begin(a); // works with C-arrays as well assert(*ai == -5); *ai = 42; // OK }
[edit] Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
P2602R2 | C++20 | there's machinery to prohibit certain non-member begin found by ADL
|
removed such machinery |
[edit] See also
(C++20) |
returns an iterator to the beginning of a read-only range (customization point object) |
(C++11)(C++14) |
returns an iterator to the beginning of a container or array (function template) |