Created on 2019-08-15.00:00:00 last changed 41 months ago
Proposed resolution:
This wording is relative to N4830.
Modify [range.access.begin] as follows:
-1- The name ranges::begin denotes a customization point object ([customization.point.object]). The expression ranges::begin(E) for some subexpression E is expression-equivalent to:
(1.1) — E + 0 if E is an lvalue of array type ([basic.compound]).
(1.2) — Otherwise, if E is an lvalue, decay-copy(E.begin()) if it is a valid expression and its type I models input_or_output_iterator.
(1.3) — Otherwise, decay-copy(begin(E)) if it is a valid expression and its type I models input_or_output_iterator with overload resolution performed in a context that includes the declarations:
and does not include a declaration of ranges::begin.template<class T> void begin(T&&) = delete; template<class T> void begin(initializer_list<T>&&) = delete;[…]
Modify [range.access.end] as follows:
-1- The name ranges::end denotes a customization point object ([customization.point.object]). The expression ranges::end(E) for some subexpression E is expression-equivalent to:
(1.1) — E + extent_v<T> if E is an lvalue of array type ([basic.compound]) T.
(1.2) — Otherwise, if E is an lvalue, decay-copy(E.end()) if it is a valid expression and its type S models sentinel_for<decltype(ranges::begin(E))>
(1.3) — Otherwise, decay-copy(end(E)) if it is a valid expression and its type S models sentinel_for<decltype(ranges::begin(E))> with overload resolution performed in a context that includes the declarations:
and does not include a declaration of ranges::end.template<class T> void end(T&&) = delete; template<class T> void end(initializer_list<T>&&) = delete;[…]
Modify [range.access.rbegin] as follows:
-1- The name ranges::rbegin denotes a customization point object ([customization.point.object]). The expression ranges::rbegin(E) for some subexpression E is expression-equivalent to:
(1.1) — If E is an lvalue, decay-copy(E.rbegin()) if it is a valid expression and its type I models input_or_output_iterator.
(1.2) — Otherwise, decay-copy(rbegin(E)) if it is a valid expression and its type I models input_or_output_iterator with overload resolution performed in a context that includes the declarations:
and does not include a declaration of ranges::rbegin.template<class T> void rbegin(T&&) = delete; template<class T> void rbegin(initializer_list<T>) = delete;[…]
Modify [range.access.rend] as follows:
-1- The name ranges::rend denotes a customization point object ([customization.point.object]). The expression ranges::rend(E) for some subexpression E is expression-equivalent to:
(1.1) — If E is an lvalue, decay-copy(E.rend()) if it is a valid expression and its type S models
sentinel_for<decltype(ranges::rbegin(E))>(1.2) — Otherwise, decay-copy(rend(E)) if it is a valid expression and its type S models
with overload resolution performed in a context that includes the declarations:sentinel_for<decltype(ranges::rbegin(E))>and does not include a declaration of ranges::rend.template<class T> void rend(T&&) = delete; template<class T> void rend(initializer_list<T>) = delete;[…]
[ 2021-06-23 Resolved by adoption of P2091R0 in Prague. Status changed: New → Resolved. ]
[ 2019-10 Priority set to 3 after reflector discussion ]
The specification of ranges::begin in [range.access.begin] includes a "poison pill" overload:
which exists to create an ambiguity with the non-member initializer_list overload of begin in namespace std ([initializer.list.syn]) when performing unqualified lookup, since specializations of initializer_list should not satisfy forwarding-range ([range.range]). The design intent is that const specializations of initializer_list should also not satisfy forwarding-range, although they are rare enough beasts that they were overlooked when this wording is written.template<class T> void begin(initializer_list<T>&&) = delete;
ranges::end ([range.access.end]) has a similar poison pill for initializer_list, which should be changed consistently.
Notably ranges::rbegin ([range.access.rbegin]) and ranges::rend ([range.access.rbegin]) as currently specified accept rvalue initializer_list arguments; they find the initializer_list overloads of std::rbegin and std::rend ([iterator.range]) via ADL. While I can't put my finger on anything in particular that's broken by this behavior, it seems wise to make rbegin and rend consistent with begin and end for initializer_list until and unless we discover a reason to do otherwise.
History | |||
---|---|---|---|
Date | User | Action | Args |
2021-06-23 13:24:25 | admin | set | messages: + msg11949 |
2021-06-23 13:24:25 | admin | set | status: new -> resolved |
2019-10-07 02:21:30 | admin | set | messages: + msg10672 |
2019-08-21 01:23:47 | admin | set | messages: + msg10569 |
2019-08-15 00:00:00 | admin | create |