From c08103b1c5012e47af6eac20d1d720ca2a4437e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorsten=20J=C3=B8rgen=20Ottosen?= Date: Fri, 9 Dec 2005 22:22:32 +0000 Subject: [PATCH] merge from 1.33.1 [SVN r31968] --- doc/boost_range.html | 990 ++++++++++++++---------- doc/example.cpp | 141 ++++ doc/intro.html | 28 +- doc/range.html | 12 +- include/boost/range/begin.hpp | 7 +- include/boost/range/difference_type.hpp | 34 +- include/boost/range/end.hpp | 37 +- include/boost/range/rbegin.hpp | 10 +- include/boost/range/rend.hpp | 14 +- include/boost/range/size_type.hpp | 55 +- include/boost/range/value_type.hpp | 30 +- test/Jamfile | 1 + test/extension_mechanism.cpp | 112 +++ 13 files changed, 1005 insertions(+), 466 deletions(-) create mode 100644 doc/example.cpp create mode 100755 test/extension_mechanism.cpp diff --git a/doc/boost_range.html b/doc/boost_range.html index 79b54c1..303f9d6 100644 --- a/doc/boost_range.html +++ b/doc/boost_range.html @@ -1,79 +1,68 @@ - - Boost.Range Range Implementation - - - - - - - - - - - -


- Boost.Range

- -

Synopsis and Reference

- - -
- - -

Overview

-

- Four types of objects are currently supported by the library: -

- - Even though the behavior of the primary templates are exactly such that standard - containers will be supported by default, the requirements are much lower than - the standard container requirements. For example, the utility class iterator_range implements - the minimal interface required to make the - class a Forward Range. -

- -

- Please also see Range concepts for more details. -

- -

Synopsis

- -

- -

+	
+		Boost.Range Reference 
+		
+		
+	
+	
+		
+			
+				
+				
+			
+		


+ Boost.Range +

+
+

Synopsis and Reference +

+ +
+ +

Overview

+

+ Four types of objects are currently supported by the library: +

+ Even though the behavior of the primary templates are exactly such that + standard containers will be supported by default, the requirements are much + lower than the standard container requirements. For example, the utility class + iterator_range implements the minimal + interface required to make the class a Forward + Range + . +

+

+ Please also see Range concepts for more details. +

+ +

Synopsis

+

+

 namespace boost
 {
     //
@@ -207,341 +196,550 @@ class=identifier>T& } // namespace 'boost' 
 
 
-

+

+ +

Semantics

+

notation

+

+ + + + + + + + + + + + + + + + +
+ Type + + Object + + Describes +
X + x + any type
T + t + denotes behavior of the primary templates
P + p + denotes std::pair<iterator,iterator>
A[sz] + a + denotes an array of type A of size sz +
Char* + s + denotes either char* or wchar_t*
+

+

+ Please notice in tables below that when four lines appear in a cell, the first + line will describe the primary template, the second line pairs of iterators, + the third line arrays and the last line null-terminated strings. +

+

Metafunctions

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Expression + Return type + Complexity
range_value<X>::typeT::value_type
+ boost::iterator_value<P::first_type>::type
+ A
+ Char +
compile time
range_iterator<X>::typeT::iterator
+ P::first_type
+ A*
+ Char* +
compile time
range_const_iterator<X>::typeT::const_iterator
+ P::first_type
+ const A*
+ const Char* +
compile time
range_difference<X>::typeT::difference_type
+ boost::iterator_difference<P::first_type>::type
+ std::ptrdiff_t
+ std::ptrdiff_t
+
compile time
range_size<X>::typeT::size_type
+ std::size_t
+ std::size_t
+ std::size_t
+
compile time
range_result_iterator<X>::typerange_const_iterator<X>::type if X is const +
+ range_iterator<X>::type otherwise +
compile time
range_reverse_iterator<X>::typeboost::reverse_iterator< typename range_iterator<T>::type >
+
compile time
range_const_reverse_iterator<X>::typeboost::reverse_iterator< typename range_const_iterator<T>::type > +
+
compile time
range_reverse_result_iterator<X>::typeboost::reverse_iterator< typename range_result_iterator<T>::type + > + compile time
+

+

+ The special metafunctions range_result_iterator and range_reverse_result_iterator + are not part of any Range concept, but they are very useful when implementing + certain Range classes like sub_range + because of their ability to select iterators based on constness. +

+

Functions

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Expression + Return type + Returns + Complexity
begin(x)range_result_iterator<X>::type + p.first if p is of type std::pair<T>
+ a if a is an array
+ s if s is a string literal
+ boost_range_begin(x) if that expression would invoke a function found by ADL
+ t.begin() otherwise + +
constant time
end(x)range_result_iterator<X>::type + p.second if p is of type std::pair<T>
+ a + sz if a is an array of size sz
+ s + std::char_traits<X>::length( s ) if s is a Char* +
+ s + sz - 1 if s is a string literal of size sz +
+ boost_range_end(x) if that expression would invoke a function found by ADL
+ t.end() otherwise + +
linear if X is Char* +
+ constant time otherwise
empty(x)boolbegin(x) == end( x )
+
linear if X is Char* +
+ constant time otherwise
+
size(x)range_size<X>::type + std::distance(p.first,p.second) if p is of type std::pair<T>
+ sz if a is an array of size sz
+ end(s) - s if s is a string literal or a Char*
+ boost_range_size(x) if that expression would invoke a function found by ADL
+ t.size() otherwise +
linear if X is Char* +
+ or if std::distance() is linear +
+ constant time otherwise
rbegin(x)range_reverse_result_iterator<X>::typerange_reverse_result_iterator<X>::type( end(x) ) +
+
same as end(x) +
rend(x)range_reverse_result_iterator<X>::typerange_reverse_result_iterator<X>::type( begin(x) ) + same as begin(x)
const_begin(x)range_const_iterator<X>::typerange_const_iterator<X>::type( begin(x) ) +
+
same as begin(x) +
const_end(x)range_const_iterator<X>::typerange_const_iterator<X>::type( end(x) ) + same as end(x)
const_rbegin(x)range_const_reverse_iterator<X>::typerange_const_reverse_iterator<X>::type( rbegin(x) ) +
+
same as rbegin(x) +
const_rend(x)range_const_reverse_iterator<X>::typerange_const_reverse_iterator<X>::type( rend(x) ) + same as rend(x)
+

+

+ The special const functions are not part of any Range concept, but + are very useful when you want to document clearly that your code is read-only. +

+
+ +

Extending the library

+ -

Semantics

+ -

notation

-

- - - - - - - - - - - - - - - -
Type - Object - Describes -
X - x - any type -
T t - denotes behavior of the primary templates
P - p - denotes std::pair<iterator,iterator> -
A[sz] - a - denotes an array of type A of size sz -
Char* - s - denotes either char* or wchar_t* -
-

+ +

Method 1: provide member functions and nested types

+ +

+ This procedure assumes that you have control over the types that should be made + conformant to a Range concept. If not, see method 2. +

+ +

+ The primary templates in this library are implemented such that standard + containers will work automatically and so will boost::array. + Below is given an overview of which member functions and member types a class + must specify to be useable as a certain Range concept. +

+

+ + + + + + + + + + + + + + + + +
+ Member function + Related concept
begin()Single Pass Range
end() + Single Pass Range
size()Forward Range
+

+

+ Notice that rbegin() and rend() member functions are + not needed even though the container can support bidirectional iteration. +

+

+ The required member types are: +

+

+ + + + + + + + + + + + + + + + + +
+ Member type + Related concept
iteratorSingle Pass Range
const_iteratorSingle Pass Range
size_typeForward Range
+

+

+ Again one should notice that member types reverse_iterator and const_reverse_iterator + are not needed. +

+ +

Method 2: provide free-standing functions and specialize metafunctions

-

- Please notice in tables below that when four lines appear in a cell, the first - line will describe the primary template, the second line pairs of iterators, the - third line arrays and the last line null-terminated strings. -

-

Metafunctions

-

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +

+ This procedure assumes that you cannot (or do not wish to) change the types that should be made + conformant to a Range concept. If this is not true, see method 1. +

+ +

+ The primary templates in this library are implemented such that + certain functions are found via argument-dependent-lookup (ADL). + Below is given an overview of which free-standing functions a class + must specify to be useable as a certain Range concept. + Let x be a variable (const or mutable) + of the class in question. +

+

+

ExpressionReturn typeComplexity
range_value<X>::typeT::value_type
- boost::iterator_value<P::first_type>::type
- A
- Char -
compile time
range_iterator<X>::typeT::iterator
- P::first_type
- A*
- Char* -
compile time
range_const_iterator<X>::typeT::const_iterator
- P::first_type
- const A*
- const Char* -
compile time
range_difference<X>::typeT::difference_type
- boost::iterator_difference<P::first_type>::type
- std::ptrdiff_t
- std::ptrdiff_t
-
compile time
range_size<X>::typeT::size_type
- std::size_t
- std::size_t
- std::size_t
-
compile time
range_result_iterator<X>::typerange_const_iterator<X>::type if X is const
- range_iterator<X>::type otherwise
compile time
range_reverse_iterator<X>::typeboost::reverse_iterator< typename range_iterator<T>::type >
-
compile time
range_const_reverse_iterator<X>::typeboost::reverse_iterator< typename range_const_iterator<T>::type > -
-
compile time
range_reverse_result_iterator<X>::typeboost::reverse_iterator< typename range_result_iterator<T>::type - > - compile time
+ + + + + + + + + + + + + + + +
+ Function + Related concept
boost_range_begin(x)Single Pass Range
boost_range_end(x) + Single Pass Range
boost_range_size(x)Forward Range
+

+

boost_range_begin() and boost_range_end() must be + overloaded for both const and mutable reference arguments. +

+ +

+ You must also specialize 3 metafunctions for your type X: +

+

+ + + + + + + + + + + + + + + + +
+ Metafunction + Related concept
boost::range_iteratorSingle Pass Range
boost::range_const_iteratorSingle Pass Range
boost::range_sizeForward Range
+

+

+ A complete example is given here: +

+
+
+#include <boost/range.hpp>
+#include <iterator>         // for std::iterator_traits, std::distance()
 
+namespace Foo
+{
+	//
+	// Our sample UDT. A 'Pair'
+	// will work as a range when the stored
+	// elements are iterators.
+	//
+	template< class T >
+	struct Pair
+	{
+		T first, last;	
+	};
 
-    
-    

-

- The special metafunctions range_result_iterator and range_reverse_result_iterator - are not part of any Range concept, but they are very useful when implementing - certain Range classes like sub_range because of their - ability to select iterators based on constness. -

+} // namespace 'Foo' -

Functions

-

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + template<classT> + structrange_size<Foo::Pair<T>> + { -
ExpressionReturn typeReturnsComplexity
begin(x)range_result_iterator<X>::typet.begin()
- p.first
- a
- s -
constant time
end(x)range_result_iterator<X>::typet.end()
- p.second
- a + sz
- s + std::char_traits<X>::length( s ) if X is Char* -
- s + sz - 1 if X is Char[sz]
+namespace boost +{ + // + // Specialize metafunctions. We must include the range.hpp header. + // We must open the 'boost' namespace. + // + template< class T > + struct range_iterator< Foo::Pair<T> > + { + typedef T type; + }; -
linear if X is Char*
- constant time otherwise
empty(x)boolbegin(x) == end( x )
-
linear if X is Char*
- constant time otherwise
-
size(x)range_size<X>::typet.size()
- std::distance(p.first,p.second)
- sz
- end(s) - s + template< class T > + struct range_const_iterator< Foo::Pair<T> > + { + // + // Remark: this is defined similar to 'range_iterator' + // because the 'Pair' type does not distinguish + // between an iterator and a const_iterator. + // + typedef T type; + }; -
linear if X is Char*
- or if std::distance() is linear
- constant time otherwise
rbegin(x)range_reverse_result_iterator<X>::typerange_reverse_result_iterator<X>::type( end(x) )
-
same as end(x)
rend(x)range_reverse_result_iterator<X>::typerange_reverse_result_iterator<X>::type( begin(x) ) - same as begin(x)
const_begin(x)range_const_iterator<X>::typerange_const_iterator<X>::type( begin(x) ) -
same as begin(x)
const_end(x)range_const_iterator<X>::typerange_const_iterator<X>::type( end(x) ) - same as end(x)
const_rbegin(x)range_const_reverse_iterator<X>::typerange_const_reverse_iterator<X>::type( rbegin(x) ) -
same as rbegin(x)
const_rend(x)range_const_reverse_iterator<X>::typerange_const_reverse_iterator<X>::type( rend(x) ) - same as rend(x)
-

- -

- The special const functions are not part of any Range concept, - but are very useful when you want to document clearly that your code is - read-only. -

+ typedef std::size_t type; + }; -
-

Extending the library

-

- The primary templates in this library are implemented such that standard - containers will work automatically and so will boost::array. Below is given an overview of - which member functions and member types a class must specify to -be useable as a certain Range concept. -

-

- - - - - - - - - - - - - - - - +}// namespace 'boost' -
Member functionRelated concept
begin()Single Pass Range
end() Single Pass Range
size()Forward Range
-

-

- Notice that rbegin() and rend() member functions - are not needed even though the container can support bidirectional iteration. -

-

- The required member types are: -

-

- - - - - - - - - - - - - - - - - - - - - - - - - - -
Member typeRelated concept
value_typeSingle Pass Range
iteratorSingle Pass Range
const_iteratorSingle Pass Range
difference_typeForward Range
size_typeForward Range
-

-

- Again one should notice that member types reverse_iterator and - const_reverse_iterator are not needed. -

- -
-

- (C) Copyright Thorsten Ottosen 2003-2004 -

+namespace Foo +{ + // + // The required functions. These should be defined in + // the same namespace as 'Pair', in this case + // in namespace 'Foo'. + // + + template< class T > + inline T boost_range_begin( Pair<T>& x ) + { + return x.first; + } -
-
-
-
-
-
-
-
-
-
-
-
+ template< class T > + inline T boost_range_begin( const Pair<T>& x ) + { + return x.first; + } + template< class T > + inline T boost_range_end( Pair<T>& x ) + { + return x.last; + } - + template< class T > + inline T boost_range_end( const Pair<T>& x ) + { + return x.last; + } + + template< class T > + inline typename boost::range_size< Pair<T> >::type + boost_range_size( const Pair<T>& x ) + { + return std::distance(x.first,x.last); + } + +} // namespace 'Foo' + +#include <vector> + +int main() +{ + typedef std::vector<int>::iterator iter; + std::vector<int> vec; + Foo::Pair<iter> pair = { vec.begin(), vec.end() }; + const Foo::Pair<iter>& cpair = pair; + // + // Notice that we call 'begin' etc with qualification. + // + iter i = boost::begin( pair ); + iter e = boost::end( pair ); + i = boost::begin( cpair ); + e = boost::end( cpair ); + boost::range_size< Foo::Pair<iter> >::type s = boost::size( pair ); + s = boost::size( cpair ); + boost::range_const_reverse_iterator< Foo::Pair<iter> >::type + ri = boost::rbegin( cpair ), + re = boost::rend( cpair ); +} +
+
+ +
+

+ (C) Copyright Thorsten Ottosen 2003-2004 +

+
+
+
+
+
+
+
+
+
+
+
+
+ diff --git a/doc/example.cpp b/doc/example.cpp new file mode 100644 index 0000000..afe448f --- /dev/null +++ b/doc/example.cpp @@ -0,0 +1,141 @@ +#include +#include // for std::iterator_traits, std::distance() + +namespace Foo +{ + // + // Our sample UDT. A 'Pair' + // will work as a range when the stored + // elements are iterators. + // + template< class T > + struct Pair + { + T first, last; + }; + +} // namespace 'Foo' + +namespace boost +{ + // + // Specialize metafunctions. We must include the range.hpp header. + // We must open the 'boost' namespace. + // + /* + template< class T > + struct range_value< Foo::Pair > + { + typedef typename std::iterator_traits::value_type type; + }; + */ + + template< class T > + struct range_iterator< Foo::Pair > + { + typedef T type; + }; + + template< class T > + struct range_const_iterator< Foo::Pair > + { + // + // Remark: this is defined similar to 'range_iterator' + // because the 'Pair' type does not distinguish + // between an iterator and a const_iterator. + // + typedef T type; + }; + + /* + template< class T > + struct range_difference< Foo::Pair > + { + typedef typename std::iterator_traits::difference_type type; + }; + */ + + template< class T > + struct range_size< Foo::Pair > + { + int static_assertion[ sizeof( std::size_t ) >= + sizeof( typename range_difference< Foo::Pair >::type ) ]; + typedef std::size_t type; + }; + +} // namespace 'boost' + +namespace Foo +{ + // + // The required functions. These should be defined in + // the same namespace as 'Pair', in this case + // in namespace 'Foo'. + // + + template< class T > + inline T boost_range_begin( Pair& x ) + { + return x.first; + } + + template< class T > + inline T boost_range_begin( const Pair& x ) + { + return x.first; + } + + template< class T > + inline T boost_range_end( Pair& x ) + { + return x.last; + } + + template< class T > + inline T boost_range_end( const Pair& x ) + { + return x.last; + } + + template< class T > + inline typename boost::range_size< Pair >::type + boost_range_size( const Pair& x ) + { + return std::distance(x.first,x.last); + } + +} // namespace 'Foo' + +#include + +int main() +{ + typedef std::vector::iterator iter; + std::vector vec; + vec.push_back( 42 ); + Foo::Pair pair = { vec.begin(), vec.end() }; + const Foo::Pair& cpair = pair; + // + // Notice that we call 'begin' etc with qualification. + // + iter i = boost::begin( pair ); + iter e = boost::end( pair ); + i = boost::begin( cpair ); + e = boost::end( cpair ); + boost::range_size< Foo::Pair >::type s = boost::size( pair ); + s = boost::size( cpair ); + boost::range_const_reverse_iterator< Foo::Pair >::type + ri = boost::rbegin( cpair ), + re = boost::rend( cpair ); + + // + // Test metafunctions + // + + boost::range_value< Foo::Pair >::type + v = *boost::begin(pair); + + boost::range_difference< Foo::Pair >::type + d = boost::end(pair) - boost::begin(pair); +} + diff --git a/doc/intro.html b/doc/intro.html index 0161f42..444b4ca 100755 --- a/doc/intro.html +++ b/doc/intro.html @@ -87,7 +87,7 @@ free-standing functions so syntactic and/or semantic differences can be removed. { return std::find( boost::begin( c ), boost::end( c ), value ); } - + template< class ForwardReadableRange, class T > inline typename boost::range_const_iterator< ForwardReadableRange >::type @@ -95,7 +95,7 @@ class=identifier>ForwardReadableRange >::{ return std::find( boost::begin( c ), boost::end( c ), value ); } - + // // replace first value and return its index // @@ -104,7 +104,7 @@ class=identifier>ForwardReadableRange >::my_generic_replace( ForwardReadableWriteableRange& c, const T& value, const T& replacement ) { typename boost::range_iterator< ForwardReadableWriteableRange >::type found = find( c, value ); - + if( found != boost::end( c ) ) *found = replacement; return std::distance( boost::begin( c ), found ); @@ -115,30 +115,30 @@ class=identifier>ForwardReadableRange >::const int N = 5; std::vector<int> my_vector; - int values[] = { 1,2,3,4,5,6,7,8,9 }; + int values[] = { 1,2,3,4,5,6,7,8,9 }; - my_vector.my_vector.assign( values, boost::end( values ) ); typedef std::vector<int>::iterator iterator; std::pair<iterator,iterator> my_view( boost::begin( my_vector ), boost::begin( my_vector ) + N ); char str_val[] = "a string"; char* str = str_val; - - std::cout << my_generic_replace( my_vector, 4, 2 ) - << my_generic_replace( my_view, 4, 2 ) - << my_generic_replace( str, 'a', 'b' ); + + std::cout << my_generic_replace( my_vector, 4, 2 ); + std::cout << my_generic_replace( my_view, 4, 2 ); + std::cout << my_generic_replace( str, 'a', 'b' ); // prints '3', '5' and '0'
- By using the free-standing functions and metafunctions, the code automatically - works for all the types supported by this library; now and in the future. + By using the free-standing functions and metafunctions, the code automatically + works for all the types supported by this library; now and in the future. Notice that we have to - provide two version of find() since we cannot forward a non-const - rvalue with reference arguments (see this article about The + provide two version of find() since we cannot forward a non-const + rvalue with reference arguments (see this article about The Forwarding Problem ).

diff --git a/doc/range.html b/doc/range.html index b2f907c..13b5ad4 100755 --- a/doc/range.html +++ b/doc/range.html @@ -386,7 +386,7 @@ VAlign="top">boost::range_const_reverse_iterator<X>::type Beginning of range - rboost::begin(a) + boost::rbegin(a) boost::range_reverse_iterator<X>::type if a is mutable, boost::range_const_reverse_iterator<X>::type otherwise. @@ -394,7 +394,7 @@ otherwise. boost::range_reverse_iterator<X>::type(boost::end(a)). End of range - rboost::end(a) + boost::rend(a) boost::range_reverse_iterator<X>::type if a is mutable, boost::range_const_reverse_iterator<X>::type otherwise. @@ -405,7 +405,7 @@ otherwise.

Complexity guarantees

- rboost::begin(a) has the same complexity as boost::end(a) and rboost::end(a) + boost::rbegin(a) has the same complexity as boost::end(a) and boost::rend(a) has the same complexity as boost::begin(a) from Forward Range. @@ -414,13 +414,13 @@ otherwise. - -
Valid reverse rangeFor any Bidirectional Range a, [rboost::begin(a),rboost::end(a)) - is a valid range, that is, rboost::end(a) is reachable from rboost::begin(a) + For any Bidirectional Range a, [boost::rbegin(a),boost::rend(a)) + is a valid range, that is, boost::rend(a) is reachable from boost::rbegin(a) in a finite number of increments.
CompletenessAn algorithm that iterates through the range [rboost::begin(a),rboost::end(a)) + An algorithm that iterates through the range [boost::rbegin(a),boost::rend(a)) will pass through every element of a.
diff --git a/include/boost/range/begin.hpp b/include/boost/range/begin.hpp index 16353eb..57ee344 100755 --- a/include/boost/range/begin.hpp +++ b/include/boost/range/begin.hpp @@ -15,6 +15,7 @@ # pragma once #endif +#include #include #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING @@ -46,7 +47,8 @@ namespace range_detail } template< typename C > - inline BOOST_DEDUCED_TYPENAME range_iterator::type + inline BOOST_DEDUCED_TYPENAME range_iterator< + typename remove_const::type >::type boost_range_begin( C& c ) { return c.begin(); @@ -140,7 +142,8 @@ namespace range_detail template< class T > -inline BOOST_DEDUCED_TYPENAME range_iterator::type begin( T& r ) +inline BOOST_DEDUCED_TYPENAME range_iterator< + typename remove_const::type >::type begin( T& r ) { #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && \ !BOOST_WORKAROUND(__GNUC__, < 3) \ diff --git a/include/boost/range/difference_type.hpp b/include/boost/range/difference_type.hpp index 1aa3246..33c56e3 100755 --- a/include/boost/range/difference_type.hpp +++ b/include/boost/range/difference_type.hpp @@ -16,12 +16,25 @@ #endif #include - -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -#include -#else - +#include #include + +namespace boost +{ + template< class T > + struct range_difference + { + typedef BOOST_DEDUCED_TYPENAME iterator_difference< + BOOST_DEDUCED_TYPENAME range_const_iterator::type >::type + type; + }; +} + +//#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +//#include +//#else + +/* #include #include @@ -30,13 +43,13 @@ namespace boost ////////////////////////////////////////////////////////////////////////// // default ////////////////////////////////////////////////////////////////////////// - + template< typename C > struct range_difference { typedef BOOST_DEDUCED_TYPENAME C::difference_type type; }; - + ////////////////////////////////////////////////////////////////////////// // pair ////////////////////////////////////////////////////////////////////////// @@ -44,14 +57,14 @@ namespace boost template< typename Iterator > struct range_difference< std::pair > { - typedef BOOST_DEDUCED_TYPENAME + typedef BOOST_DEDUCED_TYPENAME iterator_difference::type type; }; - + template< typename Iterator > struct range_difference< const std::pair > { - typedef BOOST_DEDUCED_TYPENAME + typedef BOOST_DEDUCED_TYPENAME iterator_difference::type type; }; @@ -127,5 +140,6 @@ namespace boost } // namespace boost #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +*/ #endif diff --git a/include/boost/range/end.hpp b/include/boost/range/end.hpp index 0655a47..f7eb2f8 100755 --- a/include/boost/range/end.hpp +++ b/include/boost/range/end.hpp @@ -15,6 +15,7 @@ # pragma once #endif +#include #include #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING @@ -25,34 +26,35 @@ #include #include -namespace boost +namespace boost { - + #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && \ !BOOST_WORKAROUND(__GNUC__, < 3) \ - /**/ + /**/ namespace range_detail { -#endif +#endif ////////////////////////////////////////////////////////////////////// // primary template ////////////////////////////////////////////////////////////////////// - + template< typename C > inline BOOST_DEDUCED_TYPENAME range_const_iterator::type boost_range_end( const C& c ) { return c.end(); } - + template< typename C > - inline BOOST_DEDUCED_TYPENAME range_iterator::type + inline BOOST_DEDUCED_TYPENAME range_iterator< + typename remove_const::type >::type boost_range_end( C& c ) { return c.end(); } - + ////////////////////////////////////////////////////////////////////// // pair ////////////////////////////////////////////////////////////////////// @@ -62,13 +64,13 @@ namespace range_detail { return p.second; } - + template< typename Iterator > inline Iterator boost_range_end( std::pair& p ) { return p.second; } - + ////////////////////////////////////////////////////////////////////// // array ////////////////////////////////////////////////////////////////////// @@ -76,13 +78,13 @@ namespace range_detail template< typename T, std::size_t sz > inline const T* boost_range_end( const T (&array)[sz] ) { - return range_detail::array_end( array ); + return range_detail::array_end( array ); } - + template< typename T, std::size_t sz > inline T* boost_range_end( T (&array)[sz] ) { - return range_detail::array_end( array ); + return range_detail::array_end( array ); } ////////////////////////////////////////////////////////////////////// @@ -134,18 +136,19 @@ namespace range_detail #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && \ !BOOST_WORKAROUND(__GNUC__, < 3) \ - /**/ + /**/ } // namespace 'range_detail' #endif template< class T > -inline BOOST_DEDUCED_TYPENAME range_iterator::type end( T& r ) +inline BOOST_DEDUCED_TYPENAME range_iterator< + typename remove_const::type >::type end( T& r ) { #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && \ !BOOST_WORKAROUND(__GNUC__, < 3) \ /**/ using namespace range_detail; -#endif +#endif return boost_range_end( r ); } @@ -156,7 +159,7 @@ inline BOOST_DEDUCED_TYPENAME range_const_iterator::type end( const T& r ) !BOOST_WORKAROUND(__GNUC__, < 3) \ /**/ using namespace range_detail; -#endif +#endif return boost_range_end( r ); } diff --git a/include/boost/range/rbegin.hpp b/include/boost/range/rbegin.hpp index 06b7314..f87717a 100755 --- a/include/boost/range/rbegin.hpp +++ b/include/boost/range/rbegin.hpp @@ -26,7 +26,7 @@ namespace boost #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING template< class C > -inline BOOST_DEDUCED_TYPENAME range_reverse_result_iterator::type +inline BOOST_DEDUCED_TYPENAME range_reverse_result_iterator::type rbegin( C& c ) { return BOOST_DEDUCED_TYPENAME range_reverse_result_iterator::type( end( c ) ); @@ -35,16 +35,18 @@ rbegin( C& c ) #else template< class C > -inline BOOST_DEDUCED_TYPENAME range_reverse_iterator::type +inline BOOST_DEDUCED_TYPENAME range_reverse_iterator< + typename remove_const::type >::type rbegin( C& c ) { - typedef BOOST_DEDUCED_TYPENAME range_reverse_iterator::type + typedef BOOST_DEDUCED_TYPENAME range_reverse_iterator< + typename remove_const::type >::type iter_type; return iter_type( end( c ) ); } template< class C > -inline BOOST_DEDUCED_TYPENAME range_const_reverse_iterator::type +inline BOOST_DEDUCED_TYPENAME range_const_reverse_iterator::type rbegin( const C& c ) { typedef BOOST_DEDUCED_TYPENAME range_const_reverse_iterator::type diff --git a/include/boost/range/rend.hpp b/include/boost/range/rend.hpp index 151a035..e654c60 100755 --- a/include/boost/range/rend.hpp +++ b/include/boost/range/rend.hpp @@ -22,29 +22,31 @@ namespace boost { - + #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING template< class C > -inline BOOST_DEDUCED_TYPENAME range_reverse_result_iterator::type +inline BOOST_DEDUCED_TYPENAME range_reverse_result_iterator::type rend( C& c ) { return BOOST_DEDUCED_TYPENAME range_reverse_result_iterator::type( begin( c ) ); } #else - + template< class C > -inline BOOST_DEDUCED_TYPENAME range_reverse_iterator::type +inline BOOST_DEDUCED_TYPENAME range_reverse_iterator< + typename remove_const::type >::type rend( C& c ) { - typedef BOOST_DEDUCED_TYPENAME range_reverse_iterator::type + typedef BOOST_DEDUCED_TYPENAME range_reverse_iterator< + typename remove_const::type >::type iter_type; return iter_type( begin( c ) ); } template< class C > -inline BOOST_DEDUCED_TYPENAME range_const_reverse_iterator::type +inline BOOST_DEDUCED_TYPENAME range_const_reverse_iterator::type rend( const C& c ) { typedef BOOST_DEDUCED_TYPENAME range_const_reverse_iterator::type diff --git a/include/boost/range/size_type.hpp b/include/boost/range/size_type.hpp index 3143dff..57f191d 100755 --- a/include/boost/range/size_type.hpp +++ b/include/boost/range/size_type.hpp @@ -16,6 +16,54 @@ #endif #include +/* +#include + +namespace boost +{ + namespace range_detail + { + template< class T > + struct add_unsigned; + + template<> + struct add_unsigned + { + typedef unsigned short type; + }; + + template<> + struct add_unsigned + { + typedef unsigned int type; + }; + + template<> + struct add_unsigned + { + typedef unsigned long type; + }; + +#ifdef BOOST_HAS_LONG_LONG + + template<> + struct add_unsigned + { + typedef unsigned long long type; + }; +#endif + + } + + template< class T > + struct range_size + { + typedef BOOST_DEDUCED_TYPENAME range_detail::add_unsigned< + BOOST_DEDUCED_TYPENAME range_difference::type >::type + type; + }; +} +*/ #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #include @@ -29,13 +77,13 @@ namespace boost ////////////////////////////////////////////////////////////////////////// // default ////////////////////////////////////////////////////////////////////////// - + template< typename C > struct range_size { typedef BOOST_DEDUCED_TYPENAME C::size_type type; }; - + ////////////////////////////////////////////////////////////////////////// // pair ////////////////////////////////////////////////////////////////////////// @@ -45,7 +93,7 @@ namespace boost { typedef std::size_t type; }; - + template< typename Iterator > struct range_size< const std::pair > { @@ -124,4 +172,5 @@ namespace boost #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + #endif diff --git a/include/boost/range/value_type.hpp b/include/boost/range/value_type.hpp index 7275173..15537b0 100755 --- a/include/boost/range/value_type.hpp +++ b/include/boost/range/value_type.hpp @@ -16,12 +16,26 @@ #endif #include +#include #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #include #else #include + +namespace boost +{ + template< class T > + struct range_value + { + typedef BOOST_DEDUCED_TYPENAME iterator_value< + BOOST_DEDUCED_TYPENAME range_iterator::type >::type + type; + }; +} + +/* #include #include @@ -31,13 +45,13 @@ namespace boost ////////////////////////////////////////////////////////////////////////// // default ////////////////////////////////////////////////////////////////////////// - + template< typename C > struct range_value { typedef BOOST_DEDUCED_TYPENAME C::value_type type; }; - + ////////////////////////////////////////////////////////////////////////// // pair ////////////////////////////////////////////////////////////////////////// @@ -45,15 +59,15 @@ namespace boost template< typename Iterator > struct range_value< std::pair > { - typedef BOOST_DEDUCED_TYPENAME + typedef BOOST_DEDUCED_TYPENAME iterator_value::type type; }; - - + + template< typename Iterator > struct range_value< const std::pair > { - typedef BOOST_DEDUCED_TYPENAME + typedef BOOST_DEDUCED_TYPENAME iterator_value::type type; }; @@ -72,7 +86,7 @@ namespace boost { typedef const T type; }; - + ////////////////////////////////////////////////////////////////////////// // string ////////////////////////////////////////////////////////////////////////// @@ -126,7 +140,7 @@ namespace boost }; } // namespace boost - +*/ #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #endif diff --git a/test/Jamfile b/test/Jamfile index c80a535..4a8ef6d 100755 --- a/test/Jamfile +++ b/test/Jamfile @@ -35,6 +35,7 @@ test-suite range : [ range-test algorithm_example ] [ range-test reversible_range ] [ range-test const_ranges ] + [ range-test extension_mechanism ] # [ range-test mfc : $(VC71_ROOT)/atlmfc/include ] ; diff --git a/test/extension_mechanism.cpp b/test/extension_mechanism.cpp new file mode 100755 index 0000000..0a272c3 --- /dev/null +++ b/test/extension_mechanism.cpp @@ -0,0 +1,112 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see http://www.boost.org/libs/range/ +// + + +#include + +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +# pragma warn -8091 // supress warning in Boost.Test +# pragma warn -8057 // unused argument argc/argv in Boost.Test +#endif + +#include +#include +#include +#include + +// +// Generic range algorithm +// +template< class Rng > +typename boost::range_result_iterator::type foo_algo( Rng& r ) +{ + // + // This will only compile for Rng = UDT if the qualified calls + // find boost_range_XXX via ADL. + // + return boost::size(r) == 0u ? boost::begin(r) : boost::end(r); +} + +namespace Foo +{ + // + // Our sample UDT + // + struct X + { + typedef std::vector data_t; + typedef data_t::iterator iterator; + typedef data_t::const_iterator const_iterator; + typedef data_t::size_type size_type; + + data_t vec; + + void push_back( int i ) + { vec.push_back(i); } + }; + + // + // The required functions. No type-traits need + // to be defined because X defines the proper set of + // nested types. + // + inline X::iterator boost_range_begin( X& x ) + { + return x.vec.begin(); + } + + + inline X::const_iterator boost_range_begin( const X& x ) + { + return x.vec.begin(); + } + + + inline X::iterator boost_range_end( X& x ) + { + return x.vec.end(); + } + + inline X::const_iterator boost_range_end( const X& x ) + { + return x.vec.end(); + } + + inline X::size_type boost_range_size( const X& x ) + { + return x.vec.size(); + } +} + +void check_extension() +{ + Foo::X x; + x.push_back(3); + const Foo::X x2; + + foo_algo( x ); + foo_algo( x2 ); +} + +using boost::unit_test::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Range Test Suite" ); + + test->add( BOOST_TEST_CASE( &check_extension ) ); + + return test; +} + + + + +