This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Resolved status.
initializer_listSection: 25.3.2 [range.access.begin], 25.3.3 [range.access.end], 25.3.6 [range.access.rbegin], 25.3.7 [range.access.rend] Status: Resolved Submitter: Casey Carter Opened: 2019-08-15 Last modified: 2021-06-23
Priority: 3
View all issues with Resolved status.
Discussion:
The specification of ranges::begin in 25.3.2 [range.access.begin] includes a
"poison pill" overload:
which exists to create an ambiguity with the non-membertemplate<class T> void begin(initializer_list<T>&&) = delete;
initializer_list overload of
begin in namespace std (17.11.2 [initializer.list.syn]) when performing
unqualified lookup, since specializations of initializer_list should not satisfy
forwarding-range (25.4.2 [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.
ranges::end (25.3.3 [range.access.end]) has a similar poison pill for
initializer_list, which should be changed consistently.
Notably ranges::rbegin (25.3.6 [range.access.rbegin]) and ranges::rend
(25.3.6 [range.access.rbegin]) as currently specified accept rvalue
initializer_list arguments; they find the initializer_list overloads of
std::rbegin and std::rend (24.7 [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.
[2019-10 Priority set to 3 after reflector discussion]
[2021-06-23 Resolved by adoption of P2091R0 in Prague. Status changed: New → Resolved.]
Proposed resolution:
This wording is relative to N4830.
Modify 25.3.2 [range.access.begin] as follows:
-1- The name
ranges::begindenotes a customization point object (16.3.3.3.5 [customization.point.object]). The expressionranges::begin(E)for some subexpressionEis expression-equivalent to:(1.1) —
E + 0ifEis an lvalue of array type (6.9.4 [basic.compound]).(1.2) — Otherwise, if
Eis an lvalue,decay-copy(E.begin())if it is a valid expression and its typeImodelsinput_or_output_iterator.(1.3) — Otherwise,
decay-copy(begin(E))if it is a valid expression and its typeImodelsinput_or_output_iteratorwith overload resolution performed in a context that includes the declarations:and does not include a declaration oftemplate<class T> void begin(T&&) = delete; template<class T> void begin(initializer_list<T>&&) = delete;ranges::begin.[…]
Modify 25.3.3 [range.access.end] as follows:
-1- The name
ranges::enddenotes a customization point object (16.3.3.3.5 [customization.point.object]). The expressionranges::end(E)for some subexpressionEis expression-equivalent to:(1.1) —
E + extent_v<T>ifEis an lvalue of array type (6.9.4 [basic.compound])T.(1.2) — Otherwise, if
Eis an lvalue,decay-copy(E.end())if it is a valid expression and its typeSmodelssentinel_for<decltype(ranges::begin(E))>(1.3) — Otherwise,
decay-copy(end(E))if it is a valid expression and its typeSmodelssentinel_for<decltype(ranges::begin(E))>with overload resolution performed in a context that includes the declarations:and does not include a declaration oftemplate<class T> void end(T&&) = delete; template<class T> void end(initializer_list<T>&&) = delete;ranges::end.[…]
Modify 25.3.6 [range.access.rbegin] as follows:
-1- The name
ranges::rbegindenotes a customization point object (16.3.3.3.5 [customization.point.object]). The expressionranges::rbegin(E)for some subexpressionEis expression-equivalent to:(1.1) — If
Eis an lvalue,decay-copy(E.rbegin())if it is a valid expression and its typeImodelsinput_or_output_iterator.(1.2) — Otherwise,
decay-copy(rbegin(E))if it is a valid expression and its typeImodelsinput_or_output_iteratorwith overload resolution performed in a context that includes the declarations:and does not include a declaration oftemplate<class T> void rbegin(T&&) = delete; template<class T> void rbegin(initializer_list<T>) = delete;ranges::rbegin.[…]
Modify 25.3.7 [range.access.rend] as follows:
-1- The name
ranges::renddenotes a customization point object (16.3.3.3.5 [customization.point.object]). The expressionranges::rend(E)for some subexpressionEis expression-equivalent to:(1.1) — If
Eis an lvalue,decay-copy(E.rend())if it is a valid expression and its typeSmodelssentinel_for<decltype(ranges::rbegin(E))>(1.2) — Otherwise,
decay-copy(rend(E))if it is a valid expression and its typeSmodelswith overload resolution performed in a context that includes the declarations:sentinel_for<decltype(ranges::rbegin(E))>and does not include a declaration oftemplate<class T> void rend(T&&) = delete; template<class T> void rend(initializer_list<T>) = delete;ranges::rend.[…]