Author: | Thorsten Ottosen |
---|---|
Contact: | thorsten.ottosen@dezide.com |
Advisor: | Lawrence Crowl, Douglas Gregor and Jens Maurer |
Organizations: | Dezide Aps |
Date: | 2007-05-04 |
Number: | WG21/N2243 and J16/07-0103 |
Working Group: | Core |
Abstract
This paper provides wording for the new range-based for-loop previously described in n1868, n1961, n2049 and n2196.
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 declarator
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_concept> is not included prior to a use of the range-based for statement, the program is ill-formed.
Modify paragraph 2 and 3 as indicated:
2 Otherwise (auto appearing with no type specifiers other than cv-qualifiers), or if auto appears in a for-range-declaration, the auto type-specifier signifies that the type of an object being declared shall be deduced from its initializer. The name of the object being declared shall not appear in the initializer expression.
3 This use of auto is allowed when declaring
objects in a block (6.3 stmt.block), in namespace scope (3.3.5
basic.scope.namespace), and in a for-init-statement (6.5.3 stmt.for), and
in a for-range-declaration (6.5.3 stmt.for).
Add the following to the section that describes header <iterator_concept>:
1 A class or a built-in type T satisfies the requirement 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 For an object t of a type T conforming to the Range concept, [Range<T>::begin(t),Range<T>::end(t)) designates a valid range.
3 Any object of a type conforming to the Range concept can be used with the range-based for statement (6.5.4)
Add the following new section:
namespace std { template< class T, size_t N > concept_map Range< T[N] > { see below } template<Container C> concept_map Range<C> { see below } template<Container C> concept_map Range<const C> { see below } }
Add the following new section:
1 Array objects can be used with the range-based for statement due to the following concept map:
template< class T, size_t N > concept_map Range< T[N] > { typedef T* iterator; iterator begin( T(&a)[N] ); iterator end( T(&a)[N] ); };
2 Returns: a
3 Returns: a + N
4 Any object of a type that meets the requirements of the Container concept can be used with the range-based for statement due to the following concept maps:
template<Container C> concept_map Range<C> { typedef C::iterator iterator; iterator begin( C& c ); iterator end( C& c ); }; template<Container C> concept_map Range<const C> { typedef C::const_iterator iterator; iterator begin( const C& c ); iterator end( const C& c ); };
5 Returns: c.begin();
6 Returns: c.end()
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>:
1 Initializer lists can be used with the range-based for statement due to the following concept maps:
template<typename T> concept_map Range< initializer_list<T> > { typedef const T* iterator; iterator begin( initializer_list<T>& r ); iterator end( initializer_list<T>& r ); } template<typename T> concept_map Range< const initializer_list<T> > { typedef const T* iterator; iterator begin( const initializer_list<T>& r ); iterator end( const initializer_list<T>& r ); }
2 Returns: r.begin()
3 Returns: return r.end()
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:
1 A pair object of two iterators can be used with the range-based for statement due to the following concept maps:
template<InputIterator Iter> concept_map Range< pair<Iter,Iter> > { typedef Iter iterator; Iter begin( pair<Iter,Iter>& p ); Iter end( pair<Iter,Iter>& p ); }; template<InputIterator Iter> concept_map Range< const pair<Iter,Iter> > { typedef Iter iterator; Iter begin( const pair<Iter,Iter>& p ); Iter end( const pair<Iter,Iter>& p ); };
2 Returns: p.first
3 Returns: p.second
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:
1 A tuple object of two iterators can be used with the range-based for statement due to the following concept maps:
template<InputIterator Iter> concept_map Range< tuple<Iter,Iter> > { typedef Iter iterator; Iter begin( tuple<Iter,Iter>& p ); Iter end( tuple<Iter,Iter>& p ); }; template<InputIterator Iter> concept_map Range< const tuple<Iter,Iter> > { typedef Iter iterator; Iter begin( const tuple<Iter,Iter>& p ); Iter end( const tuple<Iter,Iter>& p ); };
2 Returns: std::get<0>(p)
3 Returns: std::get<1>(p)
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:
1 valarray objects can be used with the range-based for statement due to the following concept maps.
template<class T> concept_map Range< valarray<T> > { typedef unspecified type iterator; iterator begin( valarray<T>& a ); iterator end( valarray<T>& a ); };
2 Requires: iterator shall meet the requirements of the MutableRandomAccessIterator concept
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 concept but not MutableRandomAccessIterator.
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:
1 sub_match objects can be used with the range-based for statement due to the following concept maps:
<BidirectionalIterator Iter> concept_map Range< sub_match<Iter> > { typedef Iter iterator; Iter begin( sub_match<Iter>& p ); Iter end( sub_match<Iter>& p ); }; template<BidirectionalIterator Iter> concept_map Range< const sub_match<Iter> > { typedef Iter iterator; Iter begin( const sub_match<Iter>& p ); Iter end( const sub_match<Iter>& p ); };
2 Returns: p.first
3 Returns: p.second