Wording for range-based for-loop (revision 1)

Author: Thorsten Ottosen
Contact: thorsten.ottosen@dezide.com
Advisor:Lawrence Crowl, Douglas Gregor
Organizations:Dezide Aps
Date: 2007-03-07
Number:WG21/N2196 and J16/07-0056
Working Group:Core

Abstract

This paper provides wording for the new range-based for-loop previously described in n1868, n1961 and n2049.

Table of Contents

Introduction

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 and are not part of the wording.

The author would like to thank Lawrence Crowl, Steve Adamczyk and Douglas Gregor for their help. Any mistake is the responsibility of the author.

6.5.4 The range-based for statement

1 The range-based for statement

for( type-specifier-seq simple-declarator : expression ) statement

is equivalent to

{
     auto&&  __rng(( expression ));
    
     for( auto __begin( std::Range<_RangeT>::begin(__rng) ), __end( std::Range<_RangeT>::end(__rng) );
          __begin != __end; ++__begin )
     {
         type-specifier-seq simple-declarator ( *__begin );
         statement
     }    
}

where __rng, __begin and __end are variables defined for exposition only, and _RangeT is equivalent to decltype( expression ) with any reference qualifier removed.

[Example:

std::vector<int> get_vector();
int my_array[42] = {1,2,3,4,5};

for( int& array_element : my_array )
  for( int vector_element : get_vector() )
        array_element *= vector_element;

-- end example]

2 If the header <iterator> (24.2) is not included prior to a use of the range-based for statement, the header is implicitly included.

20.2 Head <utility> synopsis

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 }

20.2.3 pair concept maps

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

20.3 Header <tuple> synopsis

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 }

20.3.1.6 tuple concept maps

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)

24.1.6 Ranges

Add the following new section:

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)

24.2 Header <iterator> synopsis

Add the following to the synopsis:

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 }

24.3.5 Range concept maps

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()

26.5.1 Header <valarray> synopsis

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 }

26.5.2.7 valarray concept maps

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.

28.4 Header <regex> synopsis

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 }

28.9.3 sub_match concept maps

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

A Grammar summary

Add the following to section A.7 after the rule for 'declarator'

simple-declarator:
    declarator-id
    ptr-operator simple-declarator