Author: | Thorsten Ottosen |
---|---|
Contact: | nesotto@cs.aau.dk |
Advisor: | Lawrence Crowl, Douglas Gregor and Jens Maurer |
Organizations: | Department of Computer Science, Aalborg University |
Date: | 2008-09-18 |
Number: | WG21/N2778 and J16/08-0288 |
Working Group: | Core |
Abstract
This paper provides wording for the new range-based for-loop previously described in n1868, n1961, n2049, n2196 , n2243 and n2394.
Table of Contents
This document provides wording for a concept-based implementation of the range-based for loop. The proposal is implemented in the latest version of Douglas Gregors Concept GCC.
Each numbered section below describes a new section for the standard or modifications to an existing section. Comments are written in bold up front and are not part of the wording.
The author would like to thank Lawrence Crowl, Steve Adamczyk and Douglas Gregor for their help with the first revisions. Special thanks goes to Jens Maurer for his help with this revision. Any mistake is the responsibility of the author.
The layout of concept headers is not yet finalized. This will only affect the library wording in minor ways and so the wording is included with any reference to the exact section in the standard.
Modify paragraph 4 as indicated:
Names declared in the for-init-statement, the for-range-declaration, and in the condition of if, while, for, and switch statements are local to the if, while, for, or switch statement (including the controlled statement), and shall not be redeclared in a subsequent condition of that statement nor in the outermost block (or, for the if statement, any of the outermost blocks) of the controlled statement; see 6.4 stmt.select.
Modify paragraph 1 as indicated:
iteration-statement: while ( condition ) statement do statement while ( expression ) ; for ( for-init-statement conditionopt ; expressionopt ) statement for ( for-range-declaration : expression ) statement for-init-statement: expression-statement simple-declaration for-range-declaration: type-specifier-seq attribute-specifieropt declarator
Editorial note: if the attribute paper is not passed, remove the attribute-specifier above.
Add the following new section:
1 The range-based for statement
for ( for-range-declaration : expression ) statement
is equivalent to
{ auto && __range = ( expression ); for ( auto __begin = std::Range<_RangeT>::begin(__range), __end = std::Range<_RangeT>::end(__range); __begin != __end; ++__begin ) { for-range-declaration = *__begin; statement } }
where __range, __begin and __end are variables defined for exposition only, and _RangeT is the type of the expression.
[Example:
int array[5] = { 1,2,3,4,5 }; for ( int& x : array ) x *= 2;
-- end example]
2 If the header <iterator_concepts> (24.1) is not included prior to a use of the range-based for statement, the program is ill-formed.
Modify paragraph 4 as indicated:
4 The auto type-specifier can also be used in declaring an object in the condition of a selection statement (6.4) or an iteration statement (6.5), in the type-specifier-seq in a new-type-id (5.3.4), in a for-range-declaration, and in declaring a static data member with a constant-initializer that appears within the member-specification of a class definition (9.4.2).
Add the following to the synopsis for header ``<iterator_concepts>``:
concept Range< typename T > see below; template< class T, size_t N > concept_map Range< T[N] > see below;
Add the following new section to [iterator.concepts]:
1 A type T satisfies the requirements of a range if it meets the syntactic and semantic requirements of the Range concept.
concept Range< typename T > { InputIterator iterator; iterator begin( T& ); iterator end( T& ); }
2 Note: Any object of a type conforming to the Range concept can be used with the range-based for statement (6.5.4).
3 Requires: For an object t of a type T conforming to the Range concept, [Range<T>::begin(t),Range<T>::end(t)) shall designate a valid range (24.1.7).
template< class T, size_t N > concept_map Range< T[N] > { typedef T* iterator; iterator begin( T(&a)[N] ) { return a; } iterator end( T(&a)[N] ) { return a + N; } };
4 Note: Adapts an array to the Range concept.
Add the following to the synopsis:
template<typename T> concept_map Range< initializer_list<T> > see below; template<typename T> concept_map Range< const initializer_list<T> > see below;
Add the following new section that describes <initializer_list>:
template<typename T> concept_map Range< initializer_list<T> > { typedef const T* iterator; iterator begin( initializer_list<T> r ) { return r.begin(); } iterator end( initializer_list<T> r ) { return r.end(); } } template<typename T> concept_map Range< const initializer_list<T> > { typedef const T* iterator; iterator begin( initializer_list<T> r ) { return r.begin(); } iterator end( initializer_list<T> r ) { return r.end(); } }
1 Note: Adapts initializer lists to the Range concept.
Add the following to the synopsis:
template<InputIterator Iter> concept_map Range< pair<Iter,Iter> > see below; template<InputIterator Iter> concept_map Range< const pair<Iter,Iter> > see below;
Add the following new section:
template<InputIterator Iter> concept_map Range< pair<Iter,Iter> > { typedef Iter iterator; Iter begin( pair<Iter,Iter>& p ) { return p.first; } Iter end( pair<Iter,Iter>& p ) { return p.second; } }; template<InputIterator Iter> concept_map Range< const pair<Iter,Iter> > { typedef Iter iterator; Iter begin( const pair<Iter,Iter>& p ) { return p.first; } Iter end( const pair<Iter,Iter>& p ) { return p.second; } };
1 Note: Adapts a pair object of two iterators to the Range concept.
Add the following to the synopsis:
template<InputIterator Iter> concept_map Range< tuple<Iter,Iter> > see below; template<InputIterator Iter> concept_map Range< const tuple<Iter,Iter> > see below;
Add the following new section:
template<InputIterator Iter> concept_map Range< tuple<Iter,Iter> > { typedef Iter iterator; Iter begin( tuple<Iter,Iter>& p ) { return std::get<0>(p); } Iter end( tuple<Iter,Iter>& p ) { return std::get<1>(p); } }; template<InputIterator Iter> concept_map Range< const tuple<Iter,Iter> > { typedef Iter iterator; Iter begin( const tuple<Iter,Iter>& p ) { return std::get<0>(p); } Iter end( const tuple<Iter,Iter>& p ) { return std::get<1>(p); } };
1 Note: Adapts a tuple object of two iterators to the Range concept.
Add the following to the end of the ``<container_concepts>'' synopsis:
template<Container C> concept_map Range<C> see below; template<Container C> concept_map Range<const C> see below;
Add the following to the end of [container.concepts.member]:
template<Container C> concept_map Range<C> { typedef C::iterator iterator; iterator begin( C& c ) { return Container<C>::begin(c); } iterator end( C& c ) { return Container<C>::end(c); } }; template<Container C> concept_map Range<const C> { typedef C::const_iterator iterator; iterator begin( const C& c ) { return Container<C>::begin(c); } iterator end( const C& c ) { return Container<C>::end(c); } };
13 Note: Adapts any type that meets the requirements of the Container concept to the Range concept.
Add the following to the synopsis:
template<class T> concept_map Range< valarray<T> > see below; template<class T> concept_map Range< const valarray<T> > see below;
Add the following new section:
template<class T> concept_map Range< valarray<T> > { typedef unspecified type iterator; iterator begin( valarray<T>& a ); iterator end( valarray<T>& a ); };
1 Note Adapts valarray to the Range concept.
2 Requires: iterator shall meet the requirements of the RandomAccessIterator concept and iterator::reference shall equal T&.
3 Returns: an iterator referencing the first value in the numeric array.
4 Returns: an iterator one past the last value in the numeric array.
template<class T> concept_map Range< const valarray<T> > { typedef unspecified type iterator; iterator begin( const valarray<T>& a ); iterator end( const valarray<T>& a ); };
5 Requires: iterator shall meet the requirements of the RandomAccessIterator and iterator::reference shall equal const T&.
6 Returns: an iterator referencing the first value in the numeric array.
7 Returns: an iterator one past the last value in the numeric array.
Add the following to the synopsis:
<BidirectionalIterator Iter> concept_map Range< sub_match<Iter> > see below; template<BidirectionalIterator Iter> concept_map Range< const sub_match<Iter> > see below;
Add the following new section:
<BidirectionalIterator Iter> concept_map Range< sub_match<Iter> > { typedef Iter iterator; Iter begin( sub_match<Iter>& p ) { return p.first; } Iter end( sub_match<Iter>& p ) { return p.second; } }; template<BidirectionalIterator Iter> concept_map Range< const sub_match<Iter> > { typedef Iter iterator; Iter begin( const sub_match<Iter>& p ) { return p.first; } Iter end( const sub_match<Iter>& p ) { return p.second; } };
1 Note: Adapts sub_match to the Range concept.