diff --git a/doc/boost_range.html b/doc/boost_range.html new file mode 100644 index 0000000..b92a786 --- /dev/null +++ b/doc/boost_range.html @@ -0,0 +1,168 @@ + Collection Traits


Collection Traits


Introduction

This library makes it possible to treat different types as if they have + implemented a subset of the container requirements + (see §23.1of the C++ standard). Formally, that subset is defined by + the CollectionConcept. + The subset deals mostly with + iterator returning functions and nested typedefs. + The main goal is to treat built-in arrays, standard containers, + pairs of iterators and some iterators uniformly. Formally, this library is an implementation + of the ExternalCollectionConcept (see also this explanation of External Concepts ).

The main advantages are

Below are given a small example (the complete example can be found here ):

+       //
+       // Example: extracting bounds in generic algorithms
+       //                
+                       
+       template< typename ExternalCollection, typename T >
+       inline typename boost::iterator_of<ExternalCollection>::type
+       find( ExternalCollection& c, const T& value )
+       {
+           return std::find( boost::begin( c ), boost::end( c ), value );
+       }
+
+       template< typename ExternalCollection, typename T >
+       inline typename boost::const_iterator_of<ExternalCollection>::type 
+       find( const ExternalCollection& c, const T& value )
+       {
+           return std::find( boost::begin( c ), boost::end( c ), value );
+       }
+                       
+       // 
+       // replace first value and return its index
+       //                                
+       template< typename EC, typename T >
+       inline typename boost::size_type_of< EC >::type
+       my_generic_replace( EC& c, const T& value, const T& replacement )
+       {
+           typename boost::const_iterator_of<EC>::type found = find( c, value );
+           *found = replacement;
+           return std::distance( boost::begin( c ), found );
+       }                  
+                       
+       // 
+       // usage
+       //                                
+       std::vector<int>              my_vector;
+       typedef vector<int>::iterator iterator;
+       std::pair<iterator,iterator>  my_view( my_vector.begin(), my_vector.begin() + N );
+       char str[] = "a string";
+       // ...
+       std::cout << my_generic_replace( my_vector, 4, 2 )
+                 << my_generic_replace( my_view, 4, 2 )
+                 << my_generic_replace( str, 'a', 'b' );
+       
By using the free-standing functions and type-generators, the code automatically + works for all the types supported by this library. 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 Forwarding Problem ).


Reference

#include <boost/collection_traits.hpp>

Five types of objects are currently supported by the library:

It is worth noticing that some functionality requires partial template specialization, in particular, + full array support does (remark: this is a very small problem since one would use boost::array<> + anyway). Also note that arrays and pointers of char or whar_t are treated special because of their use in string algorithms.

ExternalCollectionConcept

The concept is defined by the type-generators and the + functions below. Even though these functions are defined in + namespace boost, there is no such general requirement, that is, + if one wants to extend the list of supported types, it can be done in any + namespace.

Synopsis

+    namespace boost 
+    {
+        //             
+        // type generators
+        //              
+        
+        template< typename EC >                                     
+        struct value_type_of
+        {
+            typedef ... type; // type of stored objects 
+        };
+                     
+        template< typename EC >                                     
+        struct iterator_of 
+        {
+            typedef ... type; // iterator over stored objects
+        };
+        
+        template< typename EC >                                     
+        struct const_iterator_of      
+        {
+            typedef ... type; // iterator over immutable stored objects 
+        };
+
+        template< typename EC >                                     
+        struct difference_type_of
+        {
+            typedef ... type; 
+            BOOST_STATIC_ASSERT( boost::is_signed< type >::value );
+            //
+            // remark: if std::iterator_traits<> works for the type, this assertion must hold
+            //
+            BOOST_STATIC_ASSERT( boost::is_same< type, std::iterator_traits< typename 
+                                                       iterator_of< EC >::type >::difference_type>::value );         
+        };
+
+        template< typename EC >                                     
+        struct size_type_of
+        {
+            typedef ... type;
+            BOOST_STATIC_ASSERT( boost::is_unsigned< type >::value );
+            BOOST_STATIC_ASSERT( sizeof( type ) >= sizeof( difference_type_of< EC >::type ) );                   
+        };
+
+        template< typename EC >                                     
+        struct result_iterator_of     
+        {
+            typedef ... type; 
+            // iterator_of< EC >::type if EC is non-const, const_iterator_of< EC >::type otherwise         
+        };
+                     
+        //
+        // funtions
+        //
+        
+        template< typename EC >
+        inline typename iterator_of::type
+        begin( EC& c );               
+    
+        template< typename EC >
+        inline typename const_iterator_of< EC >::type
+        begin( const EC& c );                       
+            
+        template< typename EC >
+        inline typename iterator_of< EC >::type
+        end( EC& c );  
+                          
+        template< typename EC >
+        inline typename const_iterator_of< EC >::type
+        end( const EC& c );
+        
+        template< typename EC >
+        inline bool
+        empty( const EC& c );         
+                   
+        template< typename EC >
+        inline typename size_type_of< EC >::type
+        size( const EC& c );
+                     
+     } // namespace 'boost' 

Library headers

HeaderIncludes
<boost/collection_traits.hpp>everything
<boost/collection_traits/types.hpp>every type-generator
<boost/collection_traits/functions.hpp>every function
<boost/collection_traits/value_type.hpp>value_type_of
<boost/collection_traits/iterator.hpp>iterator_of
<boost/collection_traits/const_iterator.hpp>const_iterator_of
<boost/collection_traits/difference_type.hpp>difference_type_of
<boost/collection_traits/size_type.hpp>size_type_of
<boost/collection_traits/result_iterator.hpp>result_iterator_of
<boost/collection_traits/begin.hpp>begin
<boost/collection_traits/end.hpp>end
<boost/collection_traits/empty.hpp>empty
<boost/collection_traits/size.hpp>size

Semantics

In the table C is a type that conforms to the ExternalCollectionConcept and c is an object of that type. SC will denote a standard + container, T[sz] will denote an array of type T of size sz, P will denote std::pair<>, I means an iterator which default construction + denotes the end of the range and sc,t,p,i are objects of these types, + respectively. Special cases for char* and wchar_t* are described explicitly.

ExpressionReturn typeComplexity
value_type_of<C>::typeSC::value_type
T
std::iterator_traits<P::first_type>::value_type
std::iterator_traits<I>::value_type
compile time
iterator_of<C>::typeSC::iterator
T*
P::first_type
I
compile time
const_iterator_of<C>::typeSC::const_iterator
const T*
P::first_type
I
compile time
difference_type_of<C>::typeSC::difference_type
std::ptrdiff_t
std::iterator_traits<P::first_type>::difference_type
std::iterator_traits<I>::difference_type
compile time
size_type_of<C>::typeSC::size_type
std::size_t
std::size_t
std::size_t
compile time
result_iterator_of<C>::typeconst_iterator_of<C>::type if C is const
iterator_of<C>::type otherwise
compile time

ExpressionReturn typeEffectsComplexity
begin( c )result_iterator_of<C>::typesc.begin()
t
p.first
i
constant time
end( c )result_iterator_of<C>::typesc.end()
t + std::char_traits<C>::length( t ) if C is char* or wchar_t*
t + sz - 1 if C is char[sz] or wchar_t[sz]
t + sz otherwise
p.second
I()
linear if C is char* or wchar_t*
constant time otherwise
empty( c )Convertible to boolsc.empty()
size( t ) == 0
p.first == p.second
begin( i ) == end( i )
linear if C is char* or wchar_t*
constant time otherwise
size( c )size_type_of<C>::typesc.size()
end( t ) - begin( t )
distance( p.first, p.second )
not available for iterators
linear if C is char* or wchar_t*
or if std::distance() is linear
constant time otherwise

Please note that char*,whar_t*,char[], and wchar_t[] behaves differently from + normal arrays only for size() and end(). + Note that the null pointer is allowed as an argument in these cases.



Examples

Some examples are given in the accompanying test + files:


Portability

Full support for built-in arrays require that the + compiler supports class template partial specialization.

Notice that some compilers cannot do function template ordering + properly. In that case one cannot rely of result_iterator_of<> and a single function definition; instead one needs to supply + a function overloaded for const and non-const arguments if it is required.

Full support for iterators like std::istream_iterator<> depends very + much on a conforming standard library.

Most of the tests have been run successfully on these compilers


FAQ

  1. Why is there no difference between iterator_of<C>::type and const_iterator_of<C>::type for std::pair<iterator,iterator> or iterators which default construction denotes the end of the range?
  2. In general it is not possible nor desirable to find a corresponding const_iterator. When it is possible to come up with + one, the client might choose to + construct a std::pair<const_iterator,const_iterator> object.

  3. Why does the traits not supply more types or more functions?

    The traits class have been kept small because its current interface + will serve most purposes. If and when a genuine need arises for + more functionality, it can be implemented.

  4. How should I implement generic algorithms for external collections?

    One should always start with a generic algorithm that takes two iterators as input. Then use the + collection traits to build handier versions on top of the base algorithm.


History

The library have been under way for a long time. Dietmar Kühl originally + intended to submit an array_traits<> class template which had most + of the functionality present now, but only for arrays and standard containers. + Meanwhile work on container algorithms + in various context showed the need for handling pairs of iterators, and + string libraries needed special treatment of character arrays. + Thorsten Ottosen wrote everything from the ground up including the first + work-around for missing partial template specialization. Pavol Droba helped to + improve the work-around for handicapped compilers and the special character support. + The naming scheme of type-generators was suggested by Peter Dimov.


© Thorsten Ottosen 2003-2004 (nesotto_AT_cs.auc.dk). + Permission to copy, use, modify, sell and distribute this software is granted provided this copyright notice appears + in all copies. This software is provided "as is" without express or implied warranty, and with no + claim as to its suitability for any purpose.































+ \ No newline at end of file diff --git a/doc/cboost.gif b/doc/cboost.gif new file mode 100644 index 0000000..58be431 Binary files /dev/null and b/doc/cboost.gif differ diff --git a/doc/external_concepts.html b/doc/external_concepts.html new file mode 100644 index 0000000..98ccf90 --- /dev/null +++ b/doc/external_concepts.html @@ -0,0 +1,38 @@ + Concepts and External Concepts

Concepts and External Concepts

Generic programming in C++ is characterized by the use of function and class templates where + the template parameter(s) must satisfy certain requirements.Often these + requirements are so important that we give them a name: we call + such a set of type requirements a concept. We say that a type + conforms to a concept or that it is a model of a concept if it + satisfies all of those requirements. The concept can be specified as a set + of member functions with well-defined semantics + and a set of nested typedefs with well-defined properties.

Often it much more flexible to provide free-standing functions and typedefs + which provides the exact same semantics (but a different syntax) as + specified + by the concept. This allows generic code to treat different types as if + they fulfilled the concept. In this case we say that the concept has + been externalized or that the new requirements constitutes an external + concept . We say that a type conforms to an external concept + or that it is a model of an external concept . A concept may exist + without a corresponding external concept and conversely.

Whenever a concept specifies a member function, the corresponding external + concept + must specify a free-standing function of the same name, same return type and + the same argument list except there is an extra first argument which must + be of the type (or a reference to that type) that is to fulfill the external + concept. If the corresonding member function has any cv-qulifiers, the + first argument must have the same cv-qualifiers. Whenever a concept + specifies a nested typedef, the corresponding external concept + specifies a type-generator, that is, a type with a nested typedef + named type. The type-generator has the name as the nested typedef with + _of appended. + The converse relationship of an external concept and its corresponding concept + also holds.

Example:

A type T fulfills the FooConcept if it + has the follwing public members:

void T::foo( int ) const;
+ int T::bar();
+ typedef implementation defined foo_type;

The corresponding external concept is the ExternalFooConcept.

A type T fullfills the ExternalFooConcept if these + free-standing functions and type-generators exists:

void foo( const T&, int );
+ int bar( T& );
+ foo_type_of< T >::type;



Literature


© Thorsten Ottosen 2003-2004 (nesotto_AT_cs.auc.dk). + Permission to copy, use, modify, sell and distribute this software is granted provided this copyright notice appears + in all copies. This software is provided "as is" without express or implied warranty, and with no + claim as to its suitability for any purpose.































+ \ No newline at end of file diff --git a/doc/range.htm b/doc/range.htm new file mode 100755 index 0000000..2f045a0 --- /dev/null +++ b/doc/range.htm @@ -0,0 +1,612 @@ + + + +Collection + + +C++ Boost + + +
+

Collection

+ + +

Description

+ +A Collection is a concept similar to the STL Container +concept. A Collection provides iterators for accessing a range of +elements and provides information about the number of elements in the +Collection. However, a Collection has fewer requirements than a +Container. The motivation for the Collection concept is that there are +many useful Container-like types that do not meet the full +requirements of Container, and many algorithms that can be written +with this reduced set of requirements. To summarize the reduction +in requirements: + + + + +Because of the reduced requirements, some care must be taken when +writing code that is meant to be generic for all Collection types. +In particular, a Collection object should be passed by-reference +since assumptions can not be made about the behaviour of the +copy constructor. + +

+ +

Associated types

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Value type + +X::value_type + +The type of the object stored in a Collection. +If the Collection is mutable then +the value type must be Assignable. +Otherwise the value type must be CopyConstructible. +
+Iterator type + +X::iterator + +The type of iterator used to iterate through a Collection's + elements. The iterator's value type is expected to be the + Collection's value type. A conversion + from the iterator type to the const iterator type must exist. + The iterator type must be an InputIterator. +
+Const iterator type + +X::const_iterator + +A type of iterator that may be used to examine, but not to modify, + a Collection's elements. +
+Reference type + +X::reference + +A type that behaves like a reference to the Collection's value type. +[1] +
+Const reference type + +X::const_reference + +A type that behaves like a const reference to the Collection's value type. +
+Pointer type + +X::pointer + +A type that behaves as a pointer to the Collection's value type. +
+Distance type + +X::difference_type + +A signed integral type used to represent the distance between two + of the Collection's iterators. This type must be the same as + the iterator's distance type. +
+Size type + +X::size_type + +An unsigned integral type that can represent any nonnegative value + of the Collection's distance type. +
+

Notation

+ + + + + + + + + + + + + +
+X + +A type that is a model of Collection. +
+a, b + +Object of type X. +
+T + +The value type of X. +
+ +

Valid expressions

+ +The following expressions must be valid. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Name + +Expression + +Return type +
+Beginning of range + +a.begin() + +iterator if a is mutable, const_iterator otherwise +
+End of range + +a.end() + +iterator if a is mutable, const_iterator otherwise +
+Size + +a.size() + +size_type +
+Empty Collection + +a.empty() + +Convertible to bool +
+

Expression semantics

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Name + +Expression + +Semantics + +Postcondition +
+
+Beginning of range + +a.begin() + +Returns an iterator pointing to the first element in the Collection. + +a.begin() is either dereferenceable or past-the-end. It is + past-the-end if and only if a.size() == 0. +
+End of range + +a.end() + +Returns an iterator pointing one past the last element in the + Collection. + +a.end() is past-the-end. +
+Size + +a.size() + +Returns the size of the Collection, that is, its number of elements. + +a.size() >= 0 +
+Empty Collection + +a.empty() + +Equivalent to a.size() == 0. (But possibly faster.) + +  +
+

Complexity guarantees

+ +begin() and end() are amortized constant time. +

+size() is at most linear in the Collection's +size. empty() is amortized constant time. + +

Invariants

+ + + + + + + + + + + + + +
+Valid range + +For any Collection a, [a.begin(), a.end()) is a valid + range. +
+Range size + +a.size() is equal to the distance from a.begin() to a.end(). +
+Completeness + +An algorithm that iterates through the range [a.begin(), a.end()) + will pass through every element of a. +
+ + +

Models

+ + + + +

Notes

+ +

[1] + +The reference type does not have to be a real C++ reference. The +requirements of the reference type depend on the context within which +the Collection is being used. Specifically it depends on the +requirements the context places on the value type of the Collection. +The reference type of the Collection must meet the same requirements +as the value type. In addition, the reference objects must be +equivalent to the value type objects in the collection (which is +trivially true if they are the same). Also, in a mutable Collection, +an assignment to the reference object must result in an assignment to +the object in the Collection (again, which is trivially true if they +are the same object, but non-trivial if the reference type is a proxy +class). + +

See also

+Container + + +
+
+ + + + +
Copyright © 2000 +Jeremy Siek, Univ.of Notre Dame and C++ Library & Compiler Group/SGI (jsiek@engr.sgi.com) +
Copyright © 2004 +Thorsten Ottosen. +
+ + + diff --git a/index.html b/index.html new file mode 100755 index 0000000..5a83ab6 --- /dev/null +++ b/index.html @@ -0,0 +1,8 @@ + Collection Traits + + + + + + + diff --git a/test/Jamfile b/test/Jamfile new file mode 100755 index 0000000..6c15362 --- /dev/null +++ b/test/Jamfile @@ -0,0 +1,59 @@ +subproject libs/range/test ; + +SEARCH on testing.jam = $(BOOST_BUILD_PATH) ; +include testing.jam ; +DEPENDS all : test ; + +{ +test-suite range + : [ run + array.cpp + : : + : + : array_test + ] + [ run + iterator_pair.cpp + : : + : + : iterator_pair_test + ] + [ run + std_container.cpp + : : + : + : std_container_test + ] + [ run + string.cpp + : : + : + : string_test + ] + [ run + iterator_range.cpp + : : + : + : iterator_range + ] + + [ run + partial_workaround.cpp + : : + : + : workaround_test + ] + [ run + algorithm_example.cpp + : : + : + : example_test + ] + + [ run + reversible_range.cpp + : : + : + : reversible_range_test + ] ; +} diff --git a/test/TODO b/test/TODO new file mode 100644 index 0000000..e6f8058 --- /dev/null +++ b/test/TODO @@ -0,0 +1,86 @@ +1. ok. I should add something about extending the lib + how to rely on ADL. +2. | I'd prefer "primary specialization" to "default" in the comments. + ok. Is that the correct term? +3. A "specialization" of a template is the result of instantiating +it, so the more accurate term, as given in Vandevoorde and +Josuttis, is "primary template." + +5. new intro: +"When writing generic code that works with Standard Library +containers, one often finds it desirable to extend that code to +work with other types that offer enough functionality to satisfy +the needs of the generic code, but in an altered form. For +example, raw arrays are often suitable for use with generic code +that works with containers, provided a suitable adapter is used. +Likewise, null terminated strings can be treated as containers of +characters, if suitably adapted. This library provides the means +to adapt Standard Library containers, null terminated strings, +std::pairs of iterators, and raw arrays, such that the same +generic code can work with them all." + +6. > | The Introduction is missing discussion of the use of namespace +> | scope functions to do what heretofore would be done via member +> | functions. Instead, the example and the sentence immediately +> | following it imply this change of syntax. +> +> Wouldn't it only duplicate stuff in the two links to CollectionCocept and ExternalConcepts? + +In a sense, yes, but what I'm proposing is a much abbreviated +form: + +"To allow generic code to work with objects that conform to the +ExternalCollectionConcept, this library provides a set of +namespace scope functions and type +generators that provide a standard interface for the required +functionality. Whereas one might write, "c.end()," to get the end +iterator from a Standard Library container, c, using this +library, it would be written, "boost::end(c)." This change in +syntax is necessary to make the same interface possible with the +other supported types such as null terminated strings." + +7. [boost-book-style]I like colors, so perhaps use the boost-book stylesheets? + +9. New range explanation: + +I'd say "Iterable" if we have to use an "-able" term. 24.1/7 +suggests to me that "Range" might be OK: + + Most of the library's algorithmic templates that operate on data + structures have interfaces that use ranges. A range is a pair of + iterators that designate the beginning and end of the computation. A + range [i, i) is an empty range; in general, a range [i, j) refers to + the elements in the data structure starting with the one pointed to + by i and up to but not including the one pointed to by j. Range [i, + j) is valid if and only if j is reachable from i. The result of the + application of functions in the library to invalid ranges is + undefined. + +10. Don't make empty part of the Range concept, but have a default + implementation begin() == end() + spccial treatment of char*, + +11. documentation: table with entities before other tables + +12. Example of how result_iterator is used, necessary: +when designing templated classes + +template struct widget { + typedef result_iterator_of iterator; +}; + +13. better external concepts: Thorsten Ottosen wrote: +>> The documentation that's provided I found +>> sufficient, it's just of a different style than other concept +>> documentation. +> +> ok. I don't think the definition of concepts are that much more +> elaborate. What could be +> much better is the example which could follow normal concept +> standards. Is that what you had in mind? + +Yes. + +14. Change example code for my_generic_replace. + +15. More concepts: random-access range: which have constant +time size(); Cpm matthews latest article. diff --git a/test/algorithm_example.cpp b/test/algorithm_example.cpp new file mode 100755 index 0000000..e51f393 --- /dev/null +++ b/test/algorithm_example.cpp @@ -0,0 +1,65 @@ +// 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 +#include +#include +#include +#include + +namespace +{ + template< typename ExternalCollection, typename T > + inline typename boost::iterator_of::type + find( ExternalCollection& c, const T& value ) + { + return std::find( boost::begin( c ), boost::end( c ), value ); + } + + template< typename ExternalCollection, typename T > + inline typename boost::const_iterator_of::type + find( const ExternalCollection& c, const T& value ) + { + return std::find( boost::begin( c ), boost::end( c ), value ); + } + + // + // replace first value and return its index + // + template< typename EC, typename T > + inline typename boost::size_type_of< EC >::type + my_generic_replace( EC& c, const T& value, const T& replacement ) + { + typename boost::iterator_of::type found = find( c, value ); + + if( found != boost::end( c ) ) + *found = replacement; + return std::distance( boost::begin( c ), found ); + } +} + + + +int main() +{ + const int N = 5; + int v[] = { 1,2,3,4,5,6,6,7,8,9 }; + std::vector my_vector; + my_vector.assign( boost::begin( v ), boost::end( v ) ); + typedef std::vector::iterator iterator; + std::pair my_view( boost::begin( my_vector ), + boost::begin( my_vector ) + N ); + char str[] = "a string"; + + std::cout << my_generic_replace( my_vector, 4, 2 ) + << my_generic_replace( my_view, 4, 2 ) + << my_generic_replace( str, 'a', 'b' ); + return 0; +} diff --git a/test/array.cpp b/test/array.cpp new file mode 100755 index 0000000..01d3489 --- /dev/null +++ b/test/array.cpp @@ -0,0 +1,76 @@ +// 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 +#include +#include +#include +#include +#include + +using namespace boost; +using namespace std; + +void check_array() +{ + const int sz = 9; + typedef int array_t[sz]; + int my_array[sz] = { 1,2,3,4,5,6,7,8,9 }; + const array_t ca = { 1,2,3,4,5,6,7,8,10 }; + +#ifndef BOOST_CT_NO_STATIC_ASSERT + BOOST_STATIC_ASSERT(( is_same< value_type_of::type, int >::value )); + BOOST_STATIC_ASSERT(( is_same< iterator_of::type, int* >::value )); + BOOST_STATIC_ASSERT(( is_same< const_iterator_of::type, const int* >::value )); + BOOST_STATIC_ASSERT(( is_same< difference_type_of::type, std::ptrdiff_t >::value )); + BOOST_STATIC_ASSERT(( is_same< size_type_of::type, std::size_t >::value )); + BOOST_STATIC_ASSERT(( is_same< result_iterator_of::type, int* >::value )); + BOOST_STATIC_ASSERT(( is_same< result_iterator_of::type, const int* >::value )); + + BOOST_STATIC_ASSERT(( is_same< value_type_of::type, const int >::value )); + BOOST_STATIC_ASSERT(( is_same< iterator_of::type, const int* >::value )); + BOOST_STATIC_ASSERT(( is_same< const_iterator_of::type, const int* >::value )); + BOOST_STATIC_ASSERT(( is_same< difference_type_of::type, std::ptrdiff_t >::value )); + BOOST_STATIC_ASSERT(( is_same< size_type_of::type, std::size_t >::value )); + BOOST_STATIC_ASSERT(( is_same< result_iterator_of::type, const int* >::value )); + BOOST_STATIC_ASSERT(( is_same< result_iterator_of::type, const int* >::value )); +#endif + //typedef container::result_iterator iter; + //cout << typeid( iter() ).name() << endl; + + BOOST_CHECK_EQUAL( begin( my_array ), my_array ); + BOOST_CHECK_EQUAL( end( my_array ), my_array + size( my_array ) ); + BOOST_CHECK_EQUAL( empty( my_array ), false ); + //BOOST_CHECK( size( my_array ) == sizeof( sizer( my_array ) ) ); + + BOOST_CHECK_EQUAL( begin( ca ), ca ); + BOOST_CHECK_EQUAL( end( ca ), ca + size( ca ) ); + BOOST_CHECK_EQUAL( empty( ca ),false ); + //BOOST_CHECK( size( ca ) == sizeof( sizer( ca ) ) ); + +} + +#include + +using boost::unit_test_framework::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_array ) ); + + return test; +} + + + + + diff --git a/test/iterator_pair.cpp b/test/iterator_pair.cpp new file mode 100755 index 0000000..792e095 --- /dev/null +++ b/test/iterator_pair.cpp @@ -0,0 +1,92 @@ +// 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 +#include +#include +#include +#include +#include + +using namespace boost; +using boost::unit_test_framework::test_suite; + +void check_iterator_pair() +{ + typedef std::vector vec_t; + vec_t vec; + vec.push_back( 4 ); + typedef std::pair + pair_t; + typedef std::pair + const_pair_t; + typedef const pair_t const_pair_tt; + pair_t pair = std::make_pair( begin( vec ), end( vec ) ); + const_pair_t const_pair = std::make_pair( begin( vec ), end( vec ) ); + const_pair_tt constness_pair( pair ); + + + BOOST_STATIC_ASSERT(( is_same< value_type_of::type, + detail::iterator_traits::value_type>::value )); + BOOST_STATIC_ASSERT(( is_same< iterator_of::type, pair_t::first_type >::value )); + BOOST_STATIC_ASSERT(( is_same< const_iterator_of::type, pair_t::first_type >::value )); + BOOST_STATIC_ASSERT(( is_same< difference_type_of::type, + detail::iterator_traits::difference_type >::value )); + BOOST_STATIC_ASSERT(( is_same< size_type_of::type, std::size_t >::value )); + BOOST_STATIC_ASSERT(( is_same< result_iterator_of::type, pair_t::first_type >::value )); + BOOST_STATIC_ASSERT(( is_same< result_iterator_of::type, const_pair_t::first_type >::value )); + + BOOST_STATIC_ASSERT(( is_same< value_type_of::type, + detail::iterator_traits::value_type>::value )); + BOOST_STATIC_ASSERT(( is_same< iterator_of::type, const_pair_tt::first_type >::value )); + BOOST_STATIC_ASSERT(( is_same< const_iterator_of::type, const_pair_tt::first_type >::value )); + BOOST_STATIC_ASSERT(( is_same< difference_type_of::type, + detail::iterator_traits::difference_type >::value )); + BOOST_STATIC_ASSERT(( is_same< size_type_of::type, std::size_t >::value )); + BOOST_STATIC_ASSERT(( is_same< result_iterator_of::type, const_pair_tt::first_type >::value )); + BOOST_STATIC_ASSERT(( is_same< result_iterator_of::type, const_pair_tt::first_type >::value )); + + BOOST_CHECK( begin( pair ) == pair.first ); + BOOST_CHECK( end( pair ) == pair.second ); + BOOST_CHECK( empty( pair ) == (pair.first == pair.second) ); + BOOST_CHECK( size( pair ) == std::size_t( std::distance( pair.first, pair.second ) ) ); + + BOOST_CHECK( begin( const_pair ) == const_pair.first ); + BOOST_CHECK( end( const_pair ) == const_pair.second ); + BOOST_CHECK( empty( const_pair ) == (const_pair.first == const_pair.second) ); + BOOST_CHECK( size( const_pair ) == std::size_t( std::distance( const_pair.first, const_pair.second ) ) ); + + BOOST_CHECK( begin( constness_pair ) == constness_pair.first ); + BOOST_CHECK( end( constness_pair ) == constness_pair.second ); + BOOST_CHECK( empty( constness_pair ) == (constness_pair.first == const_pair.second) ); + BOOST_CHECK( size( constness_pair ) == std::size_t( std::distance( constness_pair.first, constness_pair.second ) ) ); + +} + + + +#include + +using boost::unit_test_framework::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_iterator_pair ) ); + + return test; +} + + + + + + diff --git a/test/iterator_range.cpp b/test/iterator_range.cpp new file mode 100755 index 0000000..dfd6be0 --- /dev/null +++ b/test/iterator_range.cpp @@ -0,0 +1,95 @@ +// 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 +#include +#include +#include +#include +#include + +using namespace boost; +using namespace std; + +struct add_one +{ + template< class T > + T operator()( T r ) const + { + return r + 1; + } +}; + +void check_iterator_range() +{ + typedef string::iterator iterator; + typedef string::const_iterator const_iterator; + typedef iterator_range irange; + typedef iterator_range cirange; + string str = "hello world"; + const string cstr = "const world"; + irange r = make_iterator_range( str ); + r = make_iterator_range( str.begin(), str.end() ); + cirange r2 = make_iterator_range( cstr ); + r2 = make_iterator_range( cstr.begin(), cstr.end() ); + r2 = make_iterator_range( str ); + + typedef sub_range srange; + typedef sub_range csrange; + srange s = r; + BOOST_CHECK( r == s ); + s = make_iterator_range( str ); + csrange s2 = r; + s2 = r2; + s2 = make_iterator_range( cstr ); + BOOST_CHECK( r != s2 ); + s2 = make_iterator_range( str ); + + BOOST_CHECK( r.begin() == s.begin() ); + BOOST_CHECK( r2.begin()== s2.begin() ); + BOOST_CHECK( r.end() == s.end() ); + BOOST_CHECK( r2.end() == s2.end() ); + BOOST_CHECK_EQUAL( r.size(), s.size() ); + BOOST_CHECK_EQUAL( r2.size(), s2.size() ); + + if( !r ) + BOOST_CHECK( false ); + if( !r2 ) + BOOST_CHECK( false ); + if( !s ) + BOOST_CHECK( false ); + if( !s2 ) + BOOST_CHECK( false ); + + cout << r << r2 << s << s2; + + string res = copy_range( r ); + BOOST_CHECK( equal( res.begin(), res.end(), r.begin() ) ); + string res2 = transform_range( s2, add_one() ); + BOOST_CHECK( !equal( s2.begin(), s2.end(), res2.begin() ) ); +} + +#include + +using boost::unit_test_framework::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_iterator_range ) ); + + return test; +} + + + + + diff --git a/test/partial_workaround.cpp b/test/partial_workaround.cpp new file mode 100755 index 0000000..e5277bb --- /dev/null +++ b/test/partial_workaround.cpp @@ -0,0 +1,106 @@ +// 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/ +// + +#define BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION 1 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace boost; +using namespace std; + +void check_partial_workaround() +{ + using namespace range_detail; + using type_traits::yes_type; + using type_traits::no_type; + + ////////////////////////////////////////////////////////////////////// + // string + ////////////////////////////////////////////////////////////////////// + char* c_ptr; + const char* cc_ptr; + wchar_t* w_ptr; + const wchar_t* cw_ptr; + + BOOST_STATIC_ASSERT( sizeof( yes_type ) == sizeof( is_string_impl( c_ptr ) ) ); + BOOST_STATIC_ASSERT( sizeof( yes_type ) == sizeof( is_string_impl( cc_ptr ) ) ); + BOOST_STATIC_ASSERT( sizeof( yes_type ) == sizeof( is_string_impl( w_ptr ) ) ); + BOOST_STATIC_ASSERT( sizeof( yes_type ) == sizeof( is_string_impl( cw_ptr ) ) ); + + BOOST_STATIC_ASSERT( sizeof( yes_type ) == sizeof( is_char_ptr_impl( c_ptr ) ) ); + BOOST_STATIC_ASSERT( sizeof( no_type ) == sizeof( is_char_ptr_impl( cc_ptr ) ) ); + + BOOST_STATIC_ASSERT( sizeof( yes_type ) == sizeof( is_wchar_t_ptr_impl( w_ptr ) ) ); + BOOST_STATIC_ASSERT( sizeof( no_type ) == sizeof( is_wchar_t_ptr_impl( cw_ptr ) ) ); + + BOOST_STATIC_ASSERT( sizeof( yes_type ) == sizeof( is_const_char_ptr_impl( c_ptr ) ) ); + BOOST_STATIC_ASSERT( sizeof( yes_type ) == sizeof( is_const_char_ptr_impl( cc_ptr ) ) ); + + BOOST_STATIC_ASSERT( sizeof( yes_type ) == sizeof( is_const_wchar_t_ptr_impl( w_ptr ) ) ); + BOOST_STATIC_ASSERT( sizeof( yes_type ) == sizeof( is_const_wchar_t_ptr_impl( cw_ptr ) ) ); + + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_detail::std_container_, + boost::range_detail::range< vector >::type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_detail::std_pair_, + boost::range_detail::range< pair >::type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_detail::array_, + boost::range_detail::range< int[42] >::type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_detail::char_ptr_, + boost::range_detail::range< char* >::type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_detail::const_char_ptr_, + boost::range_detail::range< const char* >::type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_detail::wchar_t_ptr_, + boost::range_detail::range< wchar_t* >::type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_detail::const_wchar_t_ptr_, + boost::range_detail::range< const wchar_t* >::type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_detail::std_container_, + boost::range_detail::range< vector >::type >::value )); + +} + + + + +#include + +using boost::unit_test_framework::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_partial_workaround ) ); + + return test; +} + + + + + + diff --git a/test/reversible_range.cpp b/test/reversible_range.cpp new file mode 100755 index 0000000..8a878c6 --- /dev/null +++ b/test/reversible_range.cpp @@ -0,0 +1,97 @@ +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace boost; +using namespace std; + +void check_iterator() +{ + typedef vector vec_t; + typedef vec_t::iterator iterator; + typedef pair pair_t; + typedef reverse_iterator_of::type rev_iterator; + typedef pair rev_pair_t; + + vec_t vec; + pair_t p = make_pair( vec.begin(), vec.end() ); + rev_pair_t rp = make_pair( rbegin( p ), rend( p ) ); + char* str = "mutable"; + const char* cstr = "not mutable"; + char a[] = "mutable"; + const char ca[] = "not mutable"; + wchar_t* wstr = L"mutable"; + const wchar_t* cwstr= L"not mutable"; + wchar_t wa[] = L"mutable"; + const wchar_t cwa[]= L"not mutable"; + + BOOST_CHECK( rbegin( vec ) == reverse_iterator_of::type( vec.end() ) ); + BOOST_CHECK( rend( vec ) == reverse_iterator_of::type( vec.begin() ) ); + BOOST_CHECK( distance( rbegin( vec ), rend( vec ) ) == distance( begin( vec ), end( vec ) ) ); + + BOOST_CHECK( rbegin( p ) == begin( rp ) ); + BOOST_CHECK( rend( p ) == end( rp ) ); + BOOST_CHECK( distance( rbegin( p ), rend( p ) ) == distance( begin( rp ), end( rp ) ) ); + BOOST_CHECK( distance( begin( p ), end( p ) ) == distance( rbegin( rp ), rend( rp ) ) ); + + BOOST_CHECK_EQUAL( &*begin( str ), &*( rend( str ) - 1 ) ); + BOOST_CHECK_EQUAL( &*( end( str ) - 1 ), &*rbegin( str ) ); + BOOST_CHECK_EQUAL( &*begin( cstr ), &*( rend( cstr ) - 1 ) ); + BOOST_CHECK_EQUAL( &*( end( cstr ) - 1 ), &*rbegin( cstr ) ); + + BOOST_CHECK_EQUAL( &*begin( a ), &*( rend( a ) - 1 ) ); + BOOST_CHECK_EQUAL( &*( end( a ) - 1 ), &*rbegin( a ) ); + BOOST_CHECK_EQUAL( &*begin( ca ), &*( rend( ca ) - 1 ) ); + BOOST_CHECK_EQUAL( &*( end( ca ) - 1 ), &*rbegin( ca ) ); + + BOOST_CHECK_EQUAL( &*begin( wstr ), &*( rend( wstr ) - 1 ) ); + BOOST_CHECK_EQUAL( &*( end( wstr ) - 1 ), &*rbegin( wstr ) ); + BOOST_CHECK_EQUAL( &*begin( cwstr ), &*( rend( cwstr ) - 1 ) ); + BOOST_CHECK_EQUAL( &*( end( cwstr ) - 1 ), &*rbegin( cwstr ) ); + + BOOST_CHECK_EQUAL( &*begin( wa ), &*( rend( wa ) - 1 ) ); + BOOST_CHECK_EQUAL( &*( end( wa ) - 1 ), &*rbegin( wa ) ); + BOOST_CHECK_EQUAL( &*begin( cwa ), &*( rend( cwa ) - 1 ) ); + BOOST_CHECK_EQUAL( &*( end( cwa ) - 1 ), &*rbegin( cwa ) ); + +} + + + +#include + +using boost::unit_test_framework::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_iterator ) ); + + return test; +} + + + + + + + diff --git a/test/std_container.cpp b/test/std_container.cpp new file mode 100755 index 0000000..c4e8c98 --- /dev/null +++ b/test/std_container.cpp @@ -0,0 +1,74 @@ +// 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 +#include +#include +#include +#include +#include + +using namespace boost; +using boost::unit_test_framework::test_suite; + +void check_std_container() +{ + typedef std::vector vec_t; + vec_t vec; + vec.push_back( 3 ); vec.push_back( 4 ); + const vec_t cvec( vec ); + + BOOST_STATIC_ASSERT(( is_same< value_type_of::type, vec_t::value_type >::value )); + BOOST_STATIC_ASSERT(( is_same< iterator_of::type, vec_t::iterator >::value )); + BOOST_STATIC_ASSERT(( is_same< const_iterator_of::type, vec_t::const_iterator >::value )); + BOOST_STATIC_ASSERT(( is_same< difference_type_of::type, vec_t::difference_type >::value )); + BOOST_STATIC_ASSERT(( is_same< size_type_of::type, vec_t::size_type >::value )); + BOOST_STATIC_ASSERT(( is_same< result_iterator_of::type, vec_t::iterator >::value )); + BOOST_STATIC_ASSERT(( is_same< result_iterator_of::type, vec_t::const_iterator >::value )); + + BOOST_STATIC_ASSERT(( is_same< value_type_of::type, vec_t::value_type >::value )); + BOOST_STATIC_ASSERT(( is_same< iterator_of::type, vec_t::iterator >::value )); + BOOST_STATIC_ASSERT(( is_same< const_iterator_of::type, vec_t::const_iterator >::value )); + BOOST_STATIC_ASSERT(( is_same< difference_type_of::type, vec_t::difference_type >::value )); + BOOST_STATIC_ASSERT(( is_same< size_type_of::type, vec_t::size_type >::value )); + + BOOST_CHECK( begin( vec ) == vec.begin() ); + BOOST_CHECK( end( vec ) == vec.end() ); + BOOST_CHECK( empty( vec ) == vec.empty() ); + BOOST_CHECK( size( vec ) == vec.size() ); + + BOOST_CHECK( begin( cvec ) == cvec.begin() ); + BOOST_CHECK( end( cvec ) == cvec.end() ); + BOOST_CHECK( empty( cvec ) == cvec.empty() ); + BOOST_CHECK( size( cvec ) == cvec.size() ); + +} + + + + +#include + +using boost::unit_test_framework::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_std_container ) ); + + return test; +} + + + + + + diff --git a/test/string.cpp b/test/string.cpp new file mode 100755 index 0000000..f759acf --- /dev/null +++ b/test/string.cpp @@ -0,0 +1,152 @@ +// 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 +#include +#include +#include +#include +#include +#include +#include +#include + +template< typename Container, typename T > +BOOST_DEDUCED_TYPENAME boost::iterator_of::type +find( Container& c, T value ) +{ + return std::find( boost::begin( c ), boost::end( c ), value ); +} + +template< typename Container, typename T > +BOOST_DEDUCED_TYPENAME boost::const_iterator_of::type +find( const Container& c, T value ) +{ + return std::find( boost::begin( c ), boost::end( c ), value ); +} + +std::vector +check_rvalue_return() +{ + return std::vector( 10, 'm' ); +} + +using namespace boost; + + +void check_char() +{ + typedef char* char_iterator_t; + typedef char char_array_t[10]; + const char* char_s = "a string"; + char my_string[] = "another string"; + const int my_string_length = 14; + + + BOOST_STATIC_ASSERT(( is_same< value_type_of::type, + detail::iterator_traits::value_type>::value )); + BOOST_STATIC_ASSERT(( is_same< iterator_of::type, char_iterator_t >::value )); + BOOST_STATIC_ASSERT(( is_same< const_iterator_of::type, const char* >::value )); + BOOST_STATIC_ASSERT(( is_same< difference_type_of::type, + ::std::ptrdiff_t >::value )); + BOOST_STATIC_ASSERT(( is_same< size_type_of::type, std::size_t >::value )); + BOOST_STATIC_ASSERT(( is_same< result_iterator_of::type, char_iterator_t >::value )); + BOOST_STATIC_ASSERT(( is_same< result_iterator_of::type, const char* >::value )); + // + // note: why does is_same< result_iterator::type, const char* >::value + // fail?!? + + BOOST_STATIC_ASSERT(( is_same< value_type_of::type, + char>::value )); + BOOST_STATIC_ASSERT(( is_same< iterator_of::type, char* >::value )); + BOOST_STATIC_ASSERT(( is_same< const_iterator_of::type, const char* >::value )); + BOOST_STATIC_ASSERT(( is_same< difference_type_of::type, + ::std::ptrdiff_t >::value )); + BOOST_STATIC_ASSERT(( is_same< size_type_of::type, std::size_t >::value )); + BOOST_STATIC_ASSERT(( is_same< result_iterator_of::type, char* >::value )); + BOOST_STATIC_ASSERT(( is_same< result_iterator_of::type, const char* >::value )); + + BOOST_CHECK_EQUAL( begin( char_s ), char_s ); + const char* end1 = begin( char_s ) + size( char_s ); + BOOST_CHECK_EQUAL( end( char_s ), end1 ); + BOOST_CHECK_EQUAL( empty( char_s ), (char_s == 0 || char_s[0] == char()) ); + BOOST_CHECK_EQUAL( size( char_s ), std::char_traits::length( char_s ) ); + + BOOST_CHECK_EQUAL( begin( my_string ), my_string ); + const char* end2 = begin( my_string ) + size( my_string ); + BOOST_CHECK_EQUAL( end( my_string ), end2 ); + BOOST_CHECK_EQUAL( empty( my_string ), (my_string == 0 || my_string[0] == char()) ); + BOOST_CHECK_EQUAL( size( my_string ), my_string_length ); + BOOST_CHECK_EQUAL( size( my_string ), std::char_traits::length( my_string ) ); + + + char to_search = 'n'; + BOOST_CHECK( find( char_s, to_search ) != end( char_s ) ); + BOOST_CHECK( find( my_string, to_search ) != end( my_string ) ); +} + + + +void check_string() +{ + check_char(); +// check_char(); +// check_char(); +// check_char(); + +#ifndef BOOST_NO_STD_WSTRING + typedef wchar_t* wchar_iterator_t; + const wchar_t* char_ws = L"a wide string"; + wchar_t my_wstring[] = L"another wide string"; + + BOOST_STATIC_ASSERT(( is_same< value_type_of::type, + detail::iterator_traits::value_type>::value )); + BOOST_STATIC_ASSERT(( is_same< iterator_of::type, wchar_iterator_t >::value )); + BOOST_STATIC_ASSERT(( is_same< const_iterator_of::type, const wchar_t* >::value )); + BOOST_STATIC_ASSERT(( is_same< difference_type_of::type, + detail::iterator_traits::difference_type >::value )); + BOOST_STATIC_ASSERT(( is_same< size_type_of::type, std::size_t >::value )); + BOOST_STATIC_ASSERT(( is_same< result_iterator_of::type, wchar_iterator_t >::value )); + BOOST_STATIC_ASSERT(( is_same< result_iterator_of::type, const wchar_t* >::value )); + + BOOST_CHECK_EQUAL( begin( char_ws ), char_ws ); + BOOST_CHECK_EQUAL( end( char_ws ), (begin( char_ws ) + size( char_ws )) ); + BOOST_CHECK_EQUAL( empty( char_ws ), (char_ws == 0 || char_ws[0] == wchar_t()) ); + BOOST_CHECK_EQUAL( size( char_ws ), std::char_traits::length( char_ws ) ); + + wchar_t to_search = L'n'; + BOOST_CHECK( find( char_ws, to_search ) != end( char_ws ) ); + BOOST_CHECK( find( my_wstring, to_search ) != end( my_wstring ) ); +#endif + + find( check_rvalue_return(), 'n' ); + +} + + + +#include + +using boost::unit_test_framework::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_string ) ); + + return test; +} + + + + + +