mirror of
				https://github.com/boostorg/utility.git
				synced 2025-10-20 20:15:30 +02:00 
			
		
		
		
	Compare commits
	
		
			33 Commits
		
	
	
		
			boost-1.21
			...
			svn-branch
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 666f5473d5 | ||
|  | 9a69a25fe8 | ||
|  | 9c3e87fe21 | ||
|  | a9ae944ae4 | ||
|  | 50ba2d419a | ||
|  | ff3a77ca5a | ||
|  | 4eaed6c23d | ||
|  | 4d0dd46471 | ||
|  | 9c2549bd00 | ||
|  | b7c8e0c17f | ||
|  | dd3cfe1837 | ||
|  | 43f525298e | ||
|  | 1bb1898ab9 | ||
|  | 9578f24be9 | ||
|  | 46fae3aed2 | ||
|  | e35f91a70a | ||
|  | 851052fcca | ||
|  | 5ef81b2952 | ||
|  | ef2851c053 | ||
|  | 0b4387cff5 | ||
|  | a40cf11fbf | ||
|  | 5c495cd223 | ||
|  | cf1296dff8 | ||
|  | d6d88db6e8 | ||
|  | 85c2a35257 | ||
|  | 836d8b1c64 | ||
|  | 98d8c8ab71 | ||
|  | db45013339 | ||
|  | a55c37e7f6 | ||
|  | 46a270fcca | ||
|  | 967856518e | ||
|  | 7f93e739fe | ||
|  | 2cd1422514 | 
| @@ -100,7 +100,7 @@ Assignment | ||||
| </UL> | ||||
|  | ||||
| <h3>See also</h3> | ||||
| <a href="http://www.sgi.com/Technology/STL/DefaultConstructible.html">DefaultConstructible</A> | ||||
| <a href="http://www.sgi.com/tech/stl/DefaultConstructible.html">DefaultConstructible</A> | ||||
| and  | ||||
| <A href="./CopyConstructible.html">CopyConstructible</A> | ||||
|  | ||||
|   | ||||
| @@ -11,7 +11,7 @@ | ||||
|   -- purpose.  It is provided "as is" without express or implied warranty. | ||||
|   --> | ||||
| <Head> | ||||
| <Title>CopyConstructible</Title> | ||||
| <Title>Copy Constructible</Title> | ||||
| </HEAD> | ||||
| <BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"  | ||||
|         ALINK="#ff0000">  | ||||
| @@ -19,10 +19,10 @@ | ||||
|      ALT="C++ Boost" width="277" height="86">  | ||||
| <!--end header--> | ||||
| <BR Clear> | ||||
| <H1>CopyConstructible</H1> | ||||
| <H1>Copy Constructible</H1> | ||||
|  | ||||
| <h3>Description</h3> | ||||
| A type is CopyConstructible if it is possible to copy objects of that | ||||
| A type is Copy Constructible if it is possible to copy objects of that | ||||
| type. | ||||
|  | ||||
| <h3>Notation</h3> | ||||
| @@ -32,7 +32,7 @@ type. | ||||
| <tt>T</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| is type that is a model of CopyConstructible | ||||
| is type that is a model of Copy Constructible | ||||
| </TD> | ||||
| </TR> | ||||
|  | ||||
| @@ -194,9 +194,9 @@ denotes the address of <tt>u</tt> | ||||
|  | ||||
| <h3>See also</h3> | ||||
| <A | ||||
| href="http://www.sgi.com/Technology/STL/DefaultConstructible.html">DefaultConstructible</A> | ||||
| href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default Constructible</A> | ||||
| and  | ||||
| <A href="http://www.sgi.com/Technology/STL/Assignable.html">Assignable</A> | ||||
| <A hrefa="./Assignable.html">Assignable</A> | ||||
|  | ||||
| <br> | ||||
| <HR> | ||||
|   | ||||
| @@ -196,7 +196,7 @@ satisfies the definition of a <i>partial ordering</i>.  The definition of | ||||
| a <i>strict weak ordering</i> is stricter, and the definition of a | ||||
| <i>total ordering</i> is stricter still. | ||||
| <h3>See also</h3> | ||||
| <A href="http://www.sgi.com/Technology/STL/EqualityComparable.html">EqualityComparable</A>, <A href="http://www.sgi.com/Technology/STL/StrictWeakOrdering.html">StrictWeakOrdering</A> | ||||
| <A href="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</A>, <A href="http://www.sgi.com/tech/stl/StrictWeakOrdering.html">StrictWeakOrdering</A> | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -21,21 +21,21 @@ | ||||
|  | ||||
| <H2> | ||||
| <A NAME="concept:MultiPassInputIterator"></A> | ||||
| MultiPassInputIterator | ||||
| Multi-Pass Input Iterator | ||||
| </H2> | ||||
|  | ||||
| This concept is a refinement of <a | ||||
| href="http://www.sgi.com/Technology/STL/InputIterator.html">InputIterator</a>, | ||||
| href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>, | ||||
| adding the requirements that the iterator can be used to make multiple | ||||
| passes through a range, and that if <TT>it1 == it2</TT> and | ||||
| <TT>it1</TT> is dereferenceable then <TT>++it1 == ++it2</TT>. The | ||||
| MultiPassInputIterator is very similar to the <a | ||||
| href="http://www.sgi.com/Technology/STL/ForwardIterator.hmtl">ForwardIterator</a>. The | ||||
| Multi-Pass Input Iterator is very similar to the <a | ||||
| href="http://www.sgi.com/tech/stl/ForwardIterator.hmtl">Forward Iterator</a>. The | ||||
| only difference is that a <a | ||||
| href="http://www.sgi.com/Technology/STL/ForwardIterator.hmtl">ForwardIterator</a> | ||||
| href="http://www.sgi.com/tech/stl/ForwardIterator.hmtl">Forward Iterator</a> | ||||
| requires the <TT>reference</TT> type to be <TT>value_type&</TT>, whereas | ||||
| MultiPassInputIterator is like <a | ||||
| href="http://www.sgi.com/Technology/STL/InputIterator.html">InputIterator</a> | ||||
| href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a> | ||||
| in that the <TT>reference</TT> type merely has to be convertible to | ||||
| <TT>value_type</TT>. | ||||
|  | ||||
| @@ -44,29 +44,29 @@ in that the <TT>reference</TT> type merely has to be convertible to | ||||
|  | ||||
| comments by Valentin Bonnard: | ||||
|  | ||||
| <p> I think that introducing MultiPassInputIterator isn't the right | ||||
| solution. Do you also want to define MultiPassBidirectionnalIterator | ||||
| and MultiPassRandomAccessIterator ? I don't, definitly. It only | ||||
| <p> I think that introducing Multi-Pass Input Iterator isn't the right | ||||
| solution. Do you also want to define Multi-Pass Bidirectionnal Iterator | ||||
| and Multi-Pass Random Access Iterator ? I don't, definitly. It only | ||||
| confuses the issue. The problem lies into the existing hierarchy of | ||||
| iterators, which mixes movabillity, modifiabillity and lvalue-ness, | ||||
| and these are clearly independant. | ||||
|  | ||||
| <p> The terms Forward, Bidirectionnal and RandomAccess are about | ||||
| <p> The terms Forward, Bidirectionnal and Random Access are about | ||||
| movabillity and shouldn't be used to mean anything else.  In a | ||||
| completly orthogonal way, iterators can be immutable, mutable, or | ||||
| neither.  Lvalueness of iterators is also orthogonal with | ||||
| immutabillity.  With these clean concepts, your MultiPassInputIterator | ||||
| is just called a ForwardIterator. | ||||
| immutabillity.  With these clean concepts, your Multi-Pass Input Iterator | ||||
| is just called a Forward Iterator. | ||||
|  | ||||
| <p>                 | ||||
| Other translations are:<br> | ||||
| std::ForwardIterator -> ForwardIterator & LvalueIterator<br> | ||||
| std::BidirectionnalIterator -> BidirectionnalIterator & LvalueIterator<br> | ||||
| std::RandomAccessIterator -> RandomAccessIterator & LvalueIterator<br> | ||||
| std::Forward Iterator -> ForwardIterator & Lvalue Iterator<br> | ||||
| std::Bidirectionnal Iterator -> Bidirectionnal Iterator & Lvalue Iterator<br> | ||||
| std::Random Access Iterator -> Random Access Iterator & Lvalue Iterator<br> | ||||
|  | ||||
| <p> | ||||
| Note that in practice the only operation not allowed on my  | ||||
| ForwardIterator which is allowed on std::ForwardIterator is  | ||||
| Forward Iterator which is allowed on std::Forward Iterator is  | ||||
| <tt>&*it</tt>. I think that <tt>&*</tt> is rarely needed in generic code. | ||||
|  | ||||
| <p> | ||||
| @@ -75,9 +75,9 @@ reply by Jeremy Siek: | ||||
| <p> | ||||
| The above analysis by Valentin is right on. Of course, there is | ||||
| the problem with backward compatibility. The current STL implementations | ||||
| are based on the old definition of ForwardIterator. The right course | ||||
| of action is to get ForwardIterator, etc. changed in the C++ standard. | ||||
| Once that is done we can drop MultiPassInputIterator. | ||||
| are based on the old definition of Forward Iterator. The right course | ||||
| of action is to get Forward Iterator, etc. changed in the C++ standard. | ||||
| Once that is done we can drop Multi-Pass Input Iterator. | ||||
|  | ||||
|  | ||||
| <br> | ||||
|   | ||||
| @@ -5,7 +5,7 @@ | ||||
| content="text/html; charset=iso-8859-1"> | ||||
| <meta name="Template" | ||||
| content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot"> | ||||
| <meta name="GENERATOR" content="Microsoft FrontPage Express 2.0"> | ||||
| <meta name="GENERATOR" content="Microsoft FrontPage 4.0"> | ||||
| <title>Call Traits</title> | ||||
| </head> | ||||
|  | ||||
| @@ -751,7 +751,7 @@ Hinnant and John Maddock.</p> | ||||
| <p>Maintained by <a href="mailto:John_Maddock@compuserve.com">John | ||||
| Maddock</a>, the latest version of this file can be found at <a | ||||
| href="http://www.boost.org/">www.boost.org</a>, and the boost | ||||
| discussion list at <a href="http://www.egroups.com/list/boost">www.egroups.com/list/boost</a>.</p> | ||||
| discussion list at <a href="http://www.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.</p> | ||||
|  | ||||
| <p>.</p> | ||||
|  | ||||
|   | ||||
| @@ -193,14 +193,14 @@ int main(int argc, char *argv[ ]) | ||||
|    int i = 2; | ||||
|    c2(i); | ||||
|    int* pi = &i; | ||||
| #if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES) | ||||
| #if (defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES)) && !defined(__ICL) | ||||
|    call_traits_checker<int*> c3; | ||||
|    c3(pi); | ||||
|    call_traits_checker<int&> c4; | ||||
|    c4(i); | ||||
|    call_traits_checker<const int&> c5; | ||||
|    c5(i); | ||||
| #if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) | ||||
| #if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__MWERKS__) | ||||
|    int a[2] = {1,2}; | ||||
|    call_traits_checker<int[2]> c6; | ||||
|    c6(a); | ||||
| @@ -238,7 +238,7 @@ int main(int argc, char *argv[ ]) | ||||
|    type_test(int&, boost::call_traits<int&>::reference) | ||||
|    type_test(const int&, boost::call_traits<int&>::const_reference) | ||||
|    type_test(int&, boost::call_traits<int&>::param_type) | ||||
| #if !(defined(__GNUC__) && (__GNUC__ < 3)) | ||||
| #if !(defined(__GNUC__) && (__GNUC__ < 4)) | ||||
|    type_test(int&, boost::call_traits<cr_type>::value_type) | ||||
|    type_test(int&, boost::call_traits<cr_type>::reference) | ||||
|    type_test(const int&, boost::call_traits<cr_type>::const_reference) | ||||
| @@ -365,6 +365,8 @@ template struct call_traits_test<int[2], true>; | ||||
|  | ||||
| #ifdef BOOST_MSVC | ||||
| unsigned int expected_failures = 10; | ||||
| #elif defined(__SUNPRO_CC) | ||||
| unsigned int expected_failures = 11; | ||||
| #elif defined(__BORLANDC__) | ||||
| unsigned int expected_failures = 2; | ||||
| #elif defined(__GNUC__) | ||||
| @@ -375,3 +377,4 @@ unsigned int expected_failures = 0; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
							
								
								
									
										31
									
								
								checked_delete_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								checked_delete_test.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| //  Boost checked_delete test program  ---------------------------------------// | ||||
|  | ||||
| //  (C) Copyright Beman Dawes 2001. 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. | ||||
|  | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
|  | ||||
| //  Revision History | ||||
| //  21 May 01  Initial version (Beman Dawes) | ||||
|  | ||||
| #include <boost/utility.hpp>  // for checked_delete | ||||
|  | ||||
| //  This program demonstrates compiler errors when trying to delete an | ||||
| //  incomplete type. | ||||
|  | ||||
| namespace | ||||
| { | ||||
|     class Incomplete; | ||||
| } | ||||
|  | ||||
| int main() | ||||
| { | ||||
|     Incomplete * p; | ||||
|     boost::checked_delete(p);          // should cause compile time error | ||||
|     Incomplete ** pa; | ||||
|     boost::checked_array_delete(pa);   // should cause compile time error | ||||
|     return 0; | ||||
| }   // main | ||||
| @@ -6,14 +6,15 @@ content="text/html; charset=iso-8859-1"> | ||||
| <meta name="Template" | ||||
| content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot"> | ||||
| <meta name="GENERATOR" content="Microsoft FrontPage Express 2.0"> | ||||
| <title>Header <boost/compressed_pair.hpp></title> | ||||
| <title>Header </title> | ||||
| <boost/compressed_pair.hpp> | ||||
| </head> | ||||
|  | ||||
| <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" | ||||
| vlink="#800080"> | ||||
|  | ||||
| <h2><img src="../../c++boost.gif" width="276" height="86">Header | ||||
| <<a href="../../boost/detail/call_traits.hpp">boost/compressed_pair.hpp</a>></h2> | ||||
| <<a href="../../boost/detail/compressed_pair.hpp">boost/compressed_pair.hpp</a>></h2> | ||||
|  | ||||
| <p>All of the contents of <boost/compressed_pair.hpp> are | ||||
| defined inside namespace boost.</p> | ||||
| @@ -41,6 +42,8 @@ public: | ||||
| 	explicit compressed_pair(first_param_type x); | ||||
| 	explicit compressed_pair(second_param_type y); | ||||
|  | ||||
| 	compressed_pair& operator=(const compressed_pair&); | ||||
|  | ||||
| 	first_reference       first(); | ||||
| 	first_const_reference first() const; | ||||
|  | ||||
| @@ -61,17 +64,19 @@ constructor, and this constructor initialises both values in the | ||||
| pair to the passed value.</p> | ||||
|  | ||||
| <p>Note that compressed_pair can not be instantiated if either of | ||||
| the template arguments is an enumerator type, unless there is | ||||
| compiler support for boost::is_enum, or if boost::is_enum is | ||||
| specialised for the enumerator type.</p> | ||||
| the template arguments is a union type, unless there is compiler | ||||
| support for boost::is_union, or if boost::is_union is specialised | ||||
| for the union type.</p> | ||||
|  | ||||
| <p>Finally, compressed_pair requires compiler support for partial | ||||
| specialisation of class templates - without that support | ||||
| compressed_pair behaves just like std::pair.</p> | ||||
| <p>Finally, a word of caution for Visual C++ 6 users: if either | ||||
| argument is an empty type, then assigning to that member will | ||||
| produce memory corruption, unless the empty type has a "do | ||||
| nothing" assignment operator defined. This is due to a bug | ||||
| in the way VC6 generates implicit assignment operators.</p> | ||||
|  | ||||
| <hr> | ||||
|  | ||||
| <p>Revised 08 March 2000</p> | ||||
| <p>Revised 08 May 2001</p> | ||||
|  | ||||
| <p><EFBFBD> Copyright boost.org 2000. Permission to copy, use, modify, | ||||
| sell and distribute this document is granted provided this | ||||
| @@ -85,7 +90,8 @@ Hinnant and John Maddock.</p> | ||||
| <p>Maintained by <a href="mailto:John_Maddock@compuserve.com">John | ||||
| Maddock</a>, the latest version of this file can be found at <a | ||||
| href="http://www.boost.org">www.boost.org</a>, and the boost | ||||
| discussion list at <a href="http://www.egroups.com/list/boost">www.egroups.com/list/boost</a>.</p> | ||||
| discussion list at <a | ||||
| href="http://www.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.</p> | ||||
|  | ||||
| <p> </p> | ||||
| </body> | ||||
|   | ||||
| @@ -15,6 +15,8 @@ | ||||
|  | ||||
| #include <boost/compressed_pair.hpp> | ||||
| #include <boost/type_traits/type_traits_test.hpp> | ||||
| #define BOOST_INCLUDE_MAIN | ||||
| #include <boost/test/test_tools.hpp> | ||||
|  | ||||
| using namespace boost; | ||||
|  | ||||
| @@ -54,101 +56,346 @@ struct non_empty2 | ||||
|    { return a.i == b.i; } | ||||
| }; | ||||
|  | ||||
| int main(int argc, char *argv[ ]) | ||||
| { | ||||
|    compressed_pair<int, double> cp1(1, 1.3); | ||||
|    assert(cp1.first() == 1); | ||||
|    assert(cp1.second() == 1.3); | ||||
|    compressed_pair<int, double> cp1b(2, 2.3); | ||||
|    assert(cp1b.first() == 2); | ||||
|    assert(cp1b.second() == 2.3); | ||||
|    swap(cp1, cp1b); | ||||
|    assert(cp1b.first() == 1); | ||||
|    assert(cp1b.second() == 1.3); | ||||
|    assert(cp1.first() == 2); | ||||
|    assert(cp1.second() == 2.3); | ||||
|    compressed_pair<non_empty1, non_empty2> cp1c(non_empty1(9)); | ||||
|    assert(cp1c.second() == non_empty2()); | ||||
|    assert(cp1c.first() == non_empty1(9)); | ||||
|    compressed_pair<non_empty1, non_empty2> cp1d(non_empty2(9)); | ||||
|    assert(cp1d.second() == non_empty2(9)); | ||||
|    assert(cp1d.first() == non_empty1()); | ||||
|  | ||||
|    compressed_pair<int, double> cp1e(cp1); | ||||
|  | ||||
|    compressed_pair<empty_UDT, int> cp2(2); | ||||
|    assert(cp2.second() == 2); | ||||
|    compressed_pair<int, empty_UDT> cp3(1); | ||||
|    assert(cp3.first() ==1); | ||||
|    compressed_pair<empty_UDT, empty_UDT> cp4; | ||||
|    compressed_pair<empty_UDT, empty_POD_UDT> cp5; | ||||
|    compressed_pair<int, empty_UDT> cp9(empty_UDT()); | ||||
|    compressed_pair<int, empty_UDT> cp10(1); | ||||
|    assert(cp10.first() == 1); | ||||
| #if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES) || !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) | ||||
|    int i = 0; | ||||
|    compressed_pair<int&, int&> cp6(i,i); | ||||
|    assert(cp6.first() == i); | ||||
|    assert(cp6.second() == i); | ||||
|    assert(&cp6.first() == &i); | ||||
|    assert(&cp6.second() == &i); | ||||
|    compressed_pair<int, double[2]> cp7; | ||||
|    cp7.first(); | ||||
|    double* pd = cp7.second(); | ||||
| #ifdef __GNUC__ | ||||
| using std::swap; | ||||
| #endif | ||||
|    soft_value_test(true, (sizeof(compressed_pair<empty_UDT, int>) < sizeof(std::pair<empty_UDT, int>))) | ||||
|    soft_value_test(true, (sizeof(compressed_pair<int, empty_UDT>) < sizeof(std::pair<int, empty_UDT>))) | ||||
|    soft_value_test(true, (sizeof(compressed_pair<empty_UDT, empty_UDT>) < sizeof(std::pair<empty_UDT, empty_UDT>))) | ||||
|    soft_value_test(true, (sizeof(compressed_pair<empty_UDT, empty_POD_UDT>) < sizeof(std::pair<empty_UDT, empty_POD_UDT>))) | ||||
|    soft_value_test(true, (sizeof(compressed_pair<empty_UDT, compressed_pair<empty_POD_UDT, int> >) < sizeof(std::pair<empty_UDT, std::pair<empty_POD_UDT, int> >))) | ||||
|  | ||||
|    return check_result(argc, argv); | ||||
| template <class T1, class T2> | ||||
| struct compressed_pair_tester | ||||
| { | ||||
|    // define the types we need: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    // define our test proc: | ||||
|    static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); | ||||
| }; | ||||
|  | ||||
| template <class T1, class T2> | ||||
| void compressed_pair_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4) | ||||
| { | ||||
| #ifndef __GNUC__ | ||||
|    // gcc 2.90 can't cope with function scope using | ||||
|    // declarations, and generates an internal compiler error... | ||||
|    using std::swap; | ||||
| #endif | ||||
|    // default construct: | ||||
|    boost::compressed_pair<T1,T2> cp1; | ||||
|    // first param construct: | ||||
|    boost::compressed_pair<T1,T2> cp2(p1); | ||||
|    cp2.second() = p2; | ||||
|    BOOST_TEST(cp2.first() == p1); | ||||
|    BOOST_TEST(cp2.second() == p2); | ||||
|    // second param construct: | ||||
|    boost::compressed_pair<T1,T2> cp3(p2); | ||||
|    cp3.first() = p1; | ||||
|    BOOST_TEST(cp3.second() == p2); | ||||
|    BOOST_TEST(cp3.first() == p1); | ||||
|    // both param construct: | ||||
|    boost::compressed_pair<T1,T2> cp4(p1, p2); | ||||
|    BOOST_TEST(cp4.first() == p1); | ||||
|    BOOST_TEST(cp4.second() == p2); | ||||
|    boost::compressed_pair<T1,T2> cp5(p3, p4); | ||||
|    BOOST_TEST(cp5.first() == p3); | ||||
|    BOOST_TEST(cp5.second() == p4); | ||||
|    // check const members: | ||||
|    const boost::compressed_pair<T1,T2>& cpr1 = cp4; | ||||
|    BOOST_TEST(cpr1.first() == p1); | ||||
|    BOOST_TEST(cpr1.second() == p2); | ||||
|  | ||||
|    // copy construct: | ||||
|    boost::compressed_pair<T1,T2> cp6(cp4); | ||||
|    BOOST_TEST(cp6.first() == p1); | ||||
|    BOOST_TEST(cp6.second() == p2); | ||||
|    // assignment: | ||||
|    cp1 = cp4; | ||||
|    BOOST_TEST(cp1.first() == p1); | ||||
|    BOOST_TEST(cp1.second() == p2); | ||||
|    cp1 = cp5; | ||||
|    BOOST_TEST(cp1.first() == p3); | ||||
|    BOOST_TEST(cp1.second() == p4); | ||||
|    // swap: | ||||
|    cp4.swap(cp5); | ||||
|    BOOST_TEST(cp4.first() == p3); | ||||
|    BOOST_TEST(cp4.second() == p4); | ||||
|    BOOST_TEST(cp5.first() == p1); | ||||
|    BOOST_TEST(cp5.second() == p2); | ||||
|    swap(cp4,cp5); | ||||
|    BOOST_TEST(cp4.first() == p1); | ||||
|    BOOST_TEST(cp4.second() == p2); | ||||
|    BOOST_TEST(cp5.first() == p3); | ||||
|    BOOST_TEST(cp5.second() == p4); | ||||
| } | ||||
|  | ||||
| // | ||||
| // instanciate some compressed pairs: | ||||
| #ifdef __MWERKS__ | ||||
| template class compressed_pair<int, double>; | ||||
| template class compressed_pair<int, int>; | ||||
| template class compressed_pair<empty_UDT, int>; | ||||
| template class compressed_pair<int, empty_UDT>; | ||||
| template class compressed_pair<empty_UDT, empty_UDT>; | ||||
| template class compressed_pair<empty_UDT, empty_POD_UDT>; | ||||
| #else | ||||
| template class boost::compressed_pair<int, double>; | ||||
| template class boost::compressed_pair<int, int>; | ||||
| template class boost::compressed_pair<empty_UDT, int>; | ||||
| template class boost::compressed_pair<int, empty_UDT>; | ||||
| template class boost::compressed_pair<empty_UDT, empty_UDT>; | ||||
| template class boost::compressed_pair<empty_UDT, empty_POD_UDT>; | ||||
| #endif | ||||
| // tests for case where one or both  | ||||
| // parameters are reference types: | ||||
| // | ||||
| template <class T1, class T2> | ||||
| struct compressed_pair_reference_tester | ||||
| { | ||||
|    // define the types we need: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    // define our test proc: | ||||
|    static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); | ||||
| }; | ||||
|  | ||||
| template <class T1, class T2> | ||||
| void compressed_pair_reference_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4) | ||||
| { | ||||
| #ifndef __GNUC__ | ||||
|    // gcc 2.90 can't cope with function scope using | ||||
|    // declarations, and generates an internal compiler error... | ||||
|    using std::swap; | ||||
| #endif | ||||
|    // both param construct: | ||||
|    boost::compressed_pair<T1,T2> cp4(p1, p2); | ||||
|    BOOST_TEST(cp4.first() == p1); | ||||
|    BOOST_TEST(cp4.second() == p2); | ||||
|    boost::compressed_pair<T1,T2> cp5(p3, p4); | ||||
|    BOOST_TEST(cp5.first() == p3); | ||||
|    BOOST_TEST(cp5.second() == p4); | ||||
|    // check const members: | ||||
|    const boost::compressed_pair<T1,T2>& cpr1 = cp4; | ||||
|    BOOST_TEST(cpr1.first() == p1); | ||||
|    BOOST_TEST(cpr1.second() == p2); | ||||
|  | ||||
|    // copy construct: | ||||
|    boost::compressed_pair<T1,T2> cp6(cp4); | ||||
|    BOOST_TEST(cp6.first() == p1); | ||||
|    BOOST_TEST(cp6.second() == p2); | ||||
|    // assignment: | ||||
|    // VC6 bug: | ||||
|    // When second() is an empty class, VC6 performs the | ||||
|    // assignment by doing a memcpy - even though the empty | ||||
|    // class is really a zero sized base class, the result | ||||
|    // is that the memory of first() gets trampled over. | ||||
|    // Similar arguments apply to the case that first() is  | ||||
|    // an empty base class. | ||||
|    // Strangely the problem is dependent upon the compiler | ||||
|    // settings - some generate the problem others do not. | ||||
|    cp4.first() = p3; | ||||
|    cp4.second() = p4; | ||||
|    BOOST_TEST(cp4.first() == p3); | ||||
|    BOOST_TEST(cp4.second() == p4); | ||||
| } | ||||
| // | ||||
| // supplimentary tests for case where first arg only is a reference type: | ||||
| // | ||||
| template <class T1, class T2> | ||||
| struct compressed_pair_reference1_tester | ||||
| { | ||||
|    // define the types we need: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    // define our test proc: | ||||
|    static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); | ||||
| }; | ||||
|  | ||||
| template <class T1, class T2> | ||||
| void compressed_pair_reference1_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4) | ||||
| { | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
| #ifndef __MWERKS__ | ||||
|    // first param construct: | ||||
|    boost::compressed_pair<T1,T2> cp2(p1); | ||||
|    cp2.second() = p2; | ||||
|    BOOST_TEST(cp2.first() == p1); | ||||
|    BOOST_TEST(cp2.second() == p2); | ||||
| #endif | ||||
| } | ||||
| // | ||||
| // now some for which only a few specific members can be instantiated, | ||||
| // first references: | ||||
| template double& compressed_pair<double, int&>::first(); | ||||
| template int& compressed_pair<double, int&>::second(); | ||||
| #if !(defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 95)) | ||||
| template compressed_pair<double, int&>::compressed_pair(int&); | ||||
| #endif | ||||
| template compressed_pair<double, int&>::compressed_pair(call_traits<double>::param_type,int&); | ||||
| // supplimentary tests for case where second arg only is a reference type: | ||||
| // | ||||
| // and then arrays: | ||||
| #ifndef __BORLANDC__ | ||||
| template call_traits<int[2]>::reference compressed_pair<double, int[2]>::second(); | ||||
| template <class T1, class T2> | ||||
| struct compressed_pair_reference2_tester | ||||
| { | ||||
|    // define the types we need: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    // define our test proc: | ||||
|    static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); | ||||
| }; | ||||
|  | ||||
| template <class T1, class T2> | ||||
| void compressed_pair_reference2_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4) | ||||
| { | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|    // second param construct: | ||||
|    boost::compressed_pair<T1,T2> cp3(p2); | ||||
|    cp3.first() = p1; | ||||
|    BOOST_TEST(cp3.second() == p2); | ||||
|    BOOST_TEST(cp3.first() == p1); | ||||
| #endif | ||||
| template call_traits<double>::reference compressed_pair<double, int[2]>::first(); | ||||
| #if !(defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 95)) | ||||
| template compressed_pair<double, int[2]>::compressed_pair(call_traits<double>::param_type); | ||||
| #endif | ||||
| template compressed_pair<double, int[2]>::compressed_pair(); | ||||
| #endif // __MWERKS__ | ||||
| #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
| } | ||||
|  | ||||
| // | ||||
| // tests for where one or the other parameter is an array: | ||||
| // | ||||
| template <class T1, class T2> | ||||
| struct compressed_pair_array1_tester | ||||
| { | ||||
|    // define the types we need: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    // define our test proc: | ||||
|    static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); | ||||
| }; | ||||
|  | ||||
| template <class T1, class T2> | ||||
| void compressed_pair_array1_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4) | ||||
| { | ||||
|   // default construct: | ||||
|    boost::compressed_pair<T1,T2> cp1; | ||||
|    // second param construct: | ||||
|    boost::compressed_pair<T1,T2> cp3(p2); | ||||
|    cp3.first()[0] = p1[0]; | ||||
|    BOOST_TEST(cp3.second() == p2); | ||||
|    BOOST_TEST(cp3.first()[0] == p1[0]); | ||||
|    // check const members: | ||||
|    const boost::compressed_pair<T1,T2>& cpr1 = cp3; | ||||
|    BOOST_TEST(cpr1.first()[0] == p1[0]); | ||||
|    BOOST_TEST(cpr1.second() == p2); | ||||
|  | ||||
|    BOOST_TEST(sizeof(T1) == sizeof(cp1.first())); | ||||
| } | ||||
|  | ||||
| template <class T1, class T2> | ||||
| struct compressed_pair_array2_tester | ||||
| { | ||||
|    // define the types we need: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    // define our test proc: | ||||
|    static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); | ||||
| }; | ||||
|  | ||||
| template <class T1, class T2> | ||||
| void compressed_pair_array2_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4) | ||||
| { | ||||
|    // default construct: | ||||
|    boost::compressed_pair<T1,T2> cp1; | ||||
|    // first param construct: | ||||
|    boost::compressed_pair<T1,T2> cp2(p1); | ||||
|    cp2.second()[0] = p2[0]; | ||||
|    BOOST_TEST(cp2.first() == p1); | ||||
|    BOOST_TEST(cp2.second()[0] == p2[0]); | ||||
|    // check const members: | ||||
|    const boost::compressed_pair<T1,T2>& cpr1 = cp2; | ||||
|    BOOST_TEST(cpr1.first() == p1); | ||||
|    BOOST_TEST(cpr1.second()[0] == p2[0]); | ||||
|  | ||||
|    BOOST_TEST(sizeof(T2) == sizeof(cp1.second())); | ||||
| } | ||||
|  | ||||
| template <class T1, class T2> | ||||
| struct compressed_pair_array_tester | ||||
| { | ||||
|    // define the types we need: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    // define our test proc: | ||||
|    static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); | ||||
| }; | ||||
|  | ||||
| template <class T1, class T2> | ||||
| void compressed_pair_array_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4) | ||||
| { | ||||
|    // default construct: | ||||
|    boost::compressed_pair<T1,T2> cp1; | ||||
|    cp1.first()[0] = p1[0]; | ||||
|    cp1.second()[0] = p2[0]; | ||||
|    BOOST_TEST(cp1.first()[0] == p1[0]); | ||||
|    BOOST_TEST(cp1.second()[0] == p2[0]); | ||||
|    // check const members: | ||||
|    const boost::compressed_pair<T1,T2>& cpr1 = cp1; | ||||
|    BOOST_TEST(cpr1.first()[0] == p1[0]); | ||||
|    BOOST_TEST(cpr1.second()[0] == p2[0]); | ||||
|  | ||||
|    BOOST_TEST(sizeof(T1) == sizeof(cp1.first())); | ||||
|    BOOST_TEST(sizeof(T2) == sizeof(cp1.second())); | ||||
| } | ||||
|  | ||||
| int test_main(int argc, char *argv[ ]) | ||||
| { | ||||
|    // declare some variables to pass to the tester: | ||||
|    non_empty1 ne1(2); | ||||
|    non_empty1 ne2(3); | ||||
|    non_empty2 ne3(4); | ||||
|    non_empty2 ne4(5); | ||||
|    empty_POD_UDT  e1; | ||||
|    empty_UDT      e2; | ||||
|  | ||||
|    // T1 != T2, both non-empty | ||||
|    compressed_pair_tester<non_empty1,non_empty2>::test(ne1, ne3, ne2, ne4); | ||||
|    // T1 != T2, T2 empty | ||||
|    compressed_pair_tester<non_empty1,empty_POD_UDT>::test(ne1, e1, ne2, e1); | ||||
|    // T1 != T2, T1 empty | ||||
|    compressed_pair_tester<empty_POD_UDT,non_empty2>::test(e1, ne3, e1, ne4); | ||||
|    // T1 != T2, both empty | ||||
|    compressed_pair_tester<empty_POD_UDT,empty_UDT>::test(e1, e2, e1, e2); | ||||
|    // T1 == T2, both non-empty | ||||
|    compressed_pair_tester<non_empty1,non_empty1>::test(ne1, ne1, ne2, ne2); | ||||
|    // T1 == T2, both empty | ||||
|    compressed_pair_tester<empty_UDT,empty_UDT>::test(e2, e2, e2, e2); | ||||
|  | ||||
|  | ||||
|    // test references: | ||||
|  | ||||
|    // T1 != T2, both non-empty | ||||
|    compressed_pair_reference_tester<non_empty1&,non_empty2>::test(ne1, ne3, ne2, ne4); | ||||
|    compressed_pair_reference_tester<non_empty1,non_empty2&>::test(ne1, ne3, ne2, ne4); | ||||
|    compressed_pair_reference1_tester<non_empty1&,non_empty2>::test(ne1, ne3, ne2, ne4); | ||||
|    compressed_pair_reference2_tester<non_empty1,non_empty2&>::test(ne1, ne3, ne2, ne4); | ||||
|    // T1 != T2, T2 empty | ||||
|    compressed_pair_reference_tester<non_empty1&,empty_POD_UDT>::test(ne1, e1, ne2, e1); | ||||
|    compressed_pair_reference1_tester<non_empty1&,empty_POD_UDT>::test(ne1, e1, ne2, e1); | ||||
|    // T1 != T2, T1 empty | ||||
|    compressed_pair_reference_tester<empty_POD_UDT,non_empty2&>::test(e1, ne3, e1, ne4); | ||||
|    compressed_pair_reference2_tester<empty_POD_UDT,non_empty2&>::test(e1, ne3, e1, ne4); | ||||
|    // T1 == T2, both non-empty | ||||
|    compressed_pair_reference_tester<non_empty1&,non_empty1&>::test(ne1, ne1, ne2, ne2); | ||||
|  | ||||
|    // tests arrays: | ||||
|    non_empty1 nea1[2]; | ||||
|    non_empty1 nea2[2]; | ||||
|    non_empty2 nea3[2]; | ||||
|    non_empty2 nea4[2]; | ||||
|    nea1[0] = non_empty1(5); | ||||
|    nea2[0] = non_empty1(6); | ||||
|    nea3[0] = non_empty2(7); | ||||
|    nea4[0] = non_empty2(8); | ||||
|     | ||||
|    // T1 != T2, both non-empty | ||||
|    compressed_pair_array1_tester<non_empty1[2],non_empty2>::test(nea1, ne3, nea2, ne4); | ||||
|    compressed_pair_array2_tester<non_empty1,non_empty2[2]>::test(ne1, nea3, ne2, nea4); | ||||
|    compressed_pair_array_tester<non_empty1[2],non_empty2[2]>::test(nea1, nea3, nea2, nea4); | ||||
|    // T1 != T2, T2 empty | ||||
|    compressed_pair_array1_tester<non_empty1[2],empty_POD_UDT>::test(nea1, e1, nea2, e1); | ||||
|    // T1 != T2, T1 empty | ||||
|    compressed_pair_array2_tester<empty_POD_UDT,non_empty2[2]>::test(e1, nea3, e1, nea4); | ||||
|    // T1 == T2, both non-empty | ||||
|    compressed_pair_array_tester<non_empty1[2],non_empty1[2]>::test(nea1, nea1, nea2, nea2); | ||||
|    return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| unsigned int expected_failures = 0; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -308,7 +308,7 @@ implementation, the <tt>difference_type</tt> for any variable-length signed | ||||
| integer type <tt>T</tt> is <tt>T</tt> itself. | ||||
|  | ||||
| <hr> | ||||
| <p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->28 Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14390" --></p> | ||||
| <p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->08 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14892" --></p> | ||||
| <p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use, | ||||
| modify, sell and distribute this document is granted provided this copyright | ||||
| notice appears in all copies. This document is provided "as is" | ||||
|   | ||||
| @@ -1,20 +1,20 @@ | ||||
| //  Boost operators.hpp header file  ----------------------------------------// | ||||
|  | ||||
| //  (C) Copyright David Abrahams 1999. 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. | ||||
|  | ||||
| //  (C) Copyright Jeremy Siek 1999. 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. | ||||
| //  (C) Copyright David Abrahams, Jeremy Siek, and Daryle Walker 1999-2001. | ||||
| //  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. | ||||
|  | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
|  | ||||
| //  Revision History | ||||
| //  29 May 01 Added operator classes for << and >>.  Added input and output | ||||
| //            iterator helper classes.  Added classes to connect equality and | ||||
| //            relational operators.  Added classes for groups of related | ||||
| //            operators.  Reimplemented example operator and iterator helper | ||||
| //            classes in terms of the new groups.  (Daryle Walker, with help | ||||
| //            from Alexy Gurtovoy) | ||||
| //  11 Feb 01 Fixed bugs in the iterator helpers which prevented explicitly | ||||
| //            supplied arguments from actually being used (Dave Abrahams) | ||||
| //  04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and | ||||
| @@ -282,12 +282,190 @@ struct indexable : B | ||||
|   } | ||||
| }; | ||||
|  | ||||
| //  More operator classes (contributed by Daryle Walker) --------------------// | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct left_shiftable2 : B | ||||
| { | ||||
|      friend T operator<<(T x, const U& y) { return x <<= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct left_shiftable1 : B | ||||
| { | ||||
|      friend T operator<<(T x, const T& y) { return x <<= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct right_shiftable2 : B | ||||
| { | ||||
|      friend T operator>>(T x, const U& y) { return x >>= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct right_shiftable1 : B | ||||
| { | ||||
|      friend T operator>>(T x, const T& y) { return x >>= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct equivalent2 : B | ||||
| { | ||||
|   friend bool operator==(const T& x, const U& y) | ||||
|   { | ||||
|     return !(x < y) && !(x > y); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct equivalent1 : B | ||||
| { | ||||
|   friend bool operator==(const T&x, const T&y) | ||||
|   { | ||||
|     return !(x < y) && !(y < x); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct partially_ordered2 : B | ||||
| { | ||||
|   friend bool operator<=(const T& x, const U& y) | ||||
|     { return (x < y) || (x == y); } | ||||
|   friend bool operator>=(const T& x, const U& y) | ||||
|     { return (x > y) || (x == y); } | ||||
|   friend bool operator>(const U& x, const T& y) | ||||
|     { return y < x; } | ||||
|   friend bool operator<(const U& x, const T& y) | ||||
|     { return y > x; } | ||||
|   friend bool operator<=(const U& x, const T& y) | ||||
|     { return (y > x) || (y == x); } | ||||
|   friend bool operator>=(const U& x, const T& y) | ||||
|     { return (y < x) || (y == x); } | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct partially_ordered1 : B | ||||
| { | ||||
|   friend bool operator>(const T& x, const T& y) | ||||
|     { return y < x; } | ||||
|   friend bool operator<=(const T& x, const T& y) | ||||
|     { return (x < y) || (x == y); } | ||||
|   friend bool operator>=(const T& x, const T& y) | ||||
|     { return (y < x) || (x == y); } | ||||
| }; | ||||
|  | ||||
| //  Combined operator classes (contributed by Daryle Walker) ----------------// | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct totally_ordered2 | ||||
|     : less_than_comparable2<T, U | ||||
|     , equality_comparable2<T, U, B | ||||
|       > > {}; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct totally_ordered1 | ||||
|     : less_than_comparable1<T | ||||
|     , equality_comparable1<T, B | ||||
|       > > {}; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct additive2 | ||||
|     : addable2<T, U | ||||
|     , subtractable2<T, U, B | ||||
|       > > {}; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct additive1 | ||||
|     : addable1<T | ||||
|     , subtractable1<T, B | ||||
|       > > {}; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct multiplicative2 | ||||
|     : multipliable2<T, U | ||||
|     , dividable2<T, U, B | ||||
|       > > {}; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct multiplicative1 | ||||
|     : multipliable1<T | ||||
|     , dividable1<T, B | ||||
|       > > {}; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct integer_multiplicative2 | ||||
|     : multiplicative2<T, U | ||||
|     , modable2<T, U, B | ||||
|       > > {}; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct integer_multiplicative1 | ||||
|     : multiplicative1<T | ||||
|     , modable1<T, B | ||||
|       > > {}; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct arithmetic2 | ||||
|     : additive2<T, U | ||||
|     , multiplicative2<T, U, B | ||||
|       > > {}; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct arithmetic1 | ||||
|     : additive1<T | ||||
|     , multiplicative1<T, B | ||||
|       > > {}; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct integer_arithmetic2 | ||||
|     : additive2<T, U | ||||
|     , integer_multiplicative2<T, U, B | ||||
|       > > {}; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct integer_arithmetic1 | ||||
|     : additive1<T | ||||
|     , integer_multiplicative1<T, B | ||||
|       > > {}; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct bitwise2 | ||||
|     : xorable2<T, U | ||||
|     , andable2<T, U | ||||
|     , orable2<T, U, B | ||||
|       > > > {}; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct bitwise1 | ||||
|     : xorable1<T | ||||
|     , andable1<T | ||||
|     , orable1<T, B | ||||
|       > > > {}; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct unit_steppable | ||||
|     : incrementable<T | ||||
|     , decrementable<T, B | ||||
|       > > {}; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct shiftable2 | ||||
|     : left_shiftable2<T, U | ||||
|     , right_shiftable2<T, U, B | ||||
|       > > {}; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct shiftable1 | ||||
|     : left_shiftable1<T | ||||
|     , right_shiftable1<T, B | ||||
|       > > {}; | ||||
|  | ||||
| #ifndef BOOST_NO_OPERATORS_IN_NAMESPACE | ||||
| } // namespace boost | ||||
| #endif // BOOST_NO_OPERATORS_IN_NAMESPACE | ||||
|  | ||||
|  | ||||
| // BOOST_IMPORT_TEMPLATE1/BOOST_IMPORT_TEMPLATE2 - | ||||
| // BOOST_IMPORT_TEMPLATE1 .. BOOST_IMPORT_TEMPLATE3 - | ||||
| // | ||||
| // When BOOST_NO_OPERATORS_IN_NAMESPACE is defined we need a way to import an | ||||
| // operator template into the boost namespace. BOOST_IMPORT_TEMPLATE1 is used | ||||
| @@ -295,12 +473,31 @@ struct indexable : B | ||||
| // two-argument forms. Note that these macros expect to be invoked from within | ||||
| // boost. | ||||
|  | ||||
| #if defined(BOOST_NO_OPERATORS_IN_NAMESPACE) | ||||
| #ifndef BOOST_NO_OPERATORS_IN_NAMESPACE | ||||
|  | ||||
| #  if defined(BOOST_NO_USING_TEMPLATE) | ||||
|   // The template is already in boost so we have nothing to do. | ||||
| # define BOOST_IMPORT_TEMPLATE3(template_name) | ||||
| # define BOOST_IMPORT_TEMPLATE2(template_name) | ||||
| # define BOOST_IMPORT_TEMPLATE1(template_name) | ||||
|  | ||||
| #else // BOOST_NO_OPERATORS_IN_NAMESPACE | ||||
|  | ||||
| #  ifndef BOOST_NO_USING_TEMPLATE | ||||
|  | ||||
|      // Bring the names in with a using-declaration | ||||
|      // to avoid stressing the compiler. | ||||
| #    define BOOST_IMPORT_TEMPLATE3(template_name) using ::template_name; | ||||
| #    define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name; | ||||
| #    define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name; | ||||
|  | ||||
| #  else | ||||
|  | ||||
|      // Otherwise, because a Borland C++ 5.5 bug prevents a using declaration | ||||
|      // from working, we are forced to use inheritance for that compiler. | ||||
| #    define BOOST_IMPORT_TEMPLATE3(template_name)                                 \ | ||||
|      template <class T, class U, class V, class B = ::boost::detail::empty_base>  \ | ||||
|      struct template_name : ::template_name<T, U, V, B> {}; | ||||
|  | ||||
|      // Because a Borland C++ 5.5 bug prevents a using declaration from working, | ||||
|      // we are forced to use inheritance for that compiler. | ||||
| #    define BOOST_IMPORT_TEMPLATE2(template_name)                              \ | ||||
|      template <class T, class U, class B = ::boost::detail::empty_base>        \ | ||||
|      struct template_name : ::template_name<T, U, B> {}; | ||||
| @@ -309,21 +506,8 @@ struct indexable : B | ||||
|      template <class T, class B = ::boost::detail::empty_base>                 \ | ||||
|      struct template_name : ::template_name<T, B> {}; | ||||
|  | ||||
| #  else | ||||
|  | ||||
|      // Otherwise, bring the names in with a using-declaration to avoid | ||||
|      // stressing the compiler | ||||
| #    define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name; | ||||
| #    define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name; | ||||
|  | ||||
| #  endif // BOOST_NO_USING_TEMPLATE | ||||
|  | ||||
| #else // !BOOST_NO_OPERATORS_IN_NAMESPACE | ||||
|  | ||||
|   // The template is already in boost so we have nothing to do. | ||||
| # define BOOST_IMPORT_TEMPLATE2(template_name) | ||||
| # define BOOST_IMPORT_TEMPLATE1(template_name) | ||||
|  | ||||
| #endif // BOOST_NO_OPERATORS_IN_NAMESPACE | ||||
|  | ||||
| // | ||||
| @@ -332,7 +516,7 @@ struct indexable : B | ||||
| // the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as | ||||
| // neccessary. | ||||
| // | ||||
| #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|  | ||||
| // is_chained_base<> - a traits class used to distinguish whether an operator | ||||
| // template argument is being used for base class chaining, or is specifying a | ||||
| @@ -355,6 +539,15 @@ template<class T> struct is_chained_base { | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| // Import a 3-type-argument operator template into boost (if neccessary) and | ||||
| // provide a specialization of 'is_chained_base<>' for it. | ||||
| # define BOOST_OPERATOR_TEMPLATE3(template_name3)                     \ | ||||
|   BOOST_IMPORT_TEMPLATE3(template_name3)                              \ | ||||
|   template<class T, class U, class V, class B>                        \ | ||||
|   struct is_chained_base< ::boost::template_name3<T, U, V, B> > {     \ | ||||
|     typedef ::boost::detail::true_t value;                            \ | ||||
|   }; | ||||
|  | ||||
| // Import a 2-type-argument operator template into boost (if neccessary) and | ||||
| // provide a specialization of 'is_chained_base<>' for it. | ||||
| # define BOOST_OPERATOR_TEMPLATE2(template_name2)                  \ | ||||
| @@ -414,6 +607,8 @@ BOOST_OPERATOR_TEMPLATE1(template_name##1) | ||||
|  | ||||
| #else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|  | ||||
| #  define BOOST_OPERATOR_TEMPLATE3(template_name3) \ | ||||
|         BOOST_IMPORT_TEMPLATE3(template_name3) | ||||
| #  define BOOST_OPERATOR_TEMPLATE2(template_name2) \ | ||||
|         BOOST_IMPORT_TEMPLATE2(template_name2) | ||||
| #  define BOOST_OPERATOR_TEMPLATE1(template_name1) \ | ||||
| @@ -442,47 +637,41 @@ BOOST_OPERATOR_TEMPLATE(orable) | ||||
|  | ||||
| BOOST_OPERATOR_TEMPLATE1(incrementable) | ||||
| BOOST_OPERATOR_TEMPLATE1(decrementable) | ||||
|  | ||||
| BOOST_OPERATOR_TEMPLATE2(dereferenceable) | ||||
| BOOST_OPERATOR_TEMPLATE3(indexable) | ||||
|  | ||||
| // indexable doesn't follow the patterns above (it has 4 template arguments), so | ||||
| // we just write out the compiler hacks explicitly. | ||||
| #ifdef BOOST_NO_OPERATORS_IN_NAMESPACE | ||||
| # ifdef BOOST_NO_USING_TEMPLATE | ||||
|    template <class T, class I, class R, class B = ::boost::detail::empty_base> | ||||
|    struct indexable : ::indexable<T,I,R,B> {}; | ||||
| # else | ||||
|    using ::indexable; | ||||
| # endif | ||||
| #endif | ||||
| BOOST_OPERATOR_TEMPLATE(left_shiftable) | ||||
| BOOST_OPERATOR_TEMPLATE(right_shiftable) | ||||
| BOOST_OPERATOR_TEMPLATE(equivalent) | ||||
| BOOST_OPERATOR_TEMPLATE(partially_ordered) | ||||
|  | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
| template <class T, class I, class R, class B> | ||||
| struct is_chained_base< ::boost::indexable<T, I, R, B> > { | ||||
|   typedef ::boost::detail::true_t operator_template_type; | ||||
| }; | ||||
| #endif | ||||
| BOOST_OPERATOR_TEMPLATE(totally_ordered) | ||||
| BOOST_OPERATOR_TEMPLATE(additive) | ||||
| BOOST_OPERATOR_TEMPLATE(multiplicative) | ||||
| BOOST_OPERATOR_TEMPLATE(integer_multiplicative) | ||||
| BOOST_OPERATOR_TEMPLATE(arithmetic) | ||||
| BOOST_OPERATOR_TEMPLATE(integer_arithmetic) | ||||
| BOOST_OPERATOR_TEMPLATE(bitwise) | ||||
| BOOST_OPERATOR_TEMPLATE1(unit_steppable) | ||||
| BOOST_OPERATOR_TEMPLATE(shiftable) | ||||
|  | ||||
| #undef BOOST_OPERATOR_TEMPLATE | ||||
| #undef BOOST_OPERATOR_TEMPLATE3 | ||||
| #undef BOOST_OPERATOR_TEMPLATE2 | ||||
| #undef BOOST_OPERATOR_TEMPLATE1 | ||||
| #undef BOOST_IMPORT_TEMPLATE1 | ||||
| #undef BOOST_IMPORT_TEMPLATE2 | ||||
| #undef BOOST_IMPORT_TEMPLATE3 | ||||
|  | ||||
| // The following 'operators' classes can only be used portably if the derived class | ||||
| // declares ALL of the required member operators. | ||||
| template <class T, class U> | ||||
| struct operators2 | ||||
|     : less_than_comparable2<T,U | ||||
|     , equality_comparable2<T,U | ||||
|     , addable2<T,U | ||||
|     , subtractable2<T,U | ||||
|     , multipliable2<T,U | ||||
|     , dividable2<T,U | ||||
|     , modable2<T,U | ||||
|     , orable2<T,U | ||||
|     , andable2<T,U | ||||
|     , xorable2<T,U | ||||
|       > > > > > > > > > > {}; | ||||
|     : totally_ordered2<T,U | ||||
|     , integer_arithmetic2<T,U | ||||
|     , bitwise2<T,U | ||||
|       > > > {}; | ||||
|  | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
| template <class T, class U = T> | ||||
| @@ -492,31 +681,47 @@ template <class T> struct operators<T, T> | ||||
| #else | ||||
| template <class T> struct operators | ||||
| #endif | ||||
|     : less_than_comparable<T | ||||
|     , equality_comparable<T | ||||
|     , addable<T | ||||
|     , subtractable<T | ||||
|     , multipliable<T | ||||
|     , dividable<T | ||||
|     , modable<T | ||||
|     , orable<T | ||||
|     , andable<T | ||||
|     , xorable<T | ||||
|     , incrementable<T | ||||
|     , decrementable<T | ||||
|       > > > > > > > > > > > > {}; | ||||
|     : totally_ordered<T | ||||
|     , integer_arithmetic<T | ||||
|     , bitwise<T | ||||
|     , unit_steppable<T | ||||
|       > > > > {}; | ||||
|  | ||||
| //  Iterator helper classes (contributed by Jeremy Siek) -------------------// | ||||
| //  (Input and output iterator helpers contributed by Daryle Walker) -------// | ||||
| //  (Changed to use combined operator classes by Daryle Walker) ------------// | ||||
| template <class T, | ||||
|           class V, | ||||
|           class D = std::ptrdiff_t, | ||||
|           class P = V const *, | ||||
|           class R = V const &> | ||||
| struct input_iterator_helper | ||||
|   : equality_comparable1<T | ||||
|   , incrementable<T | ||||
|   , dereferenceable<T, P | ||||
|   , boost::iterator<std::input_iterator_tag, V, D, P, R | ||||
|     > > > > {}; | ||||
| #ifndef BOOST_MSVC | ||||
| template <class T, | ||||
|           class V = void, | ||||
|           class D = void, | ||||
|           class P = void, | ||||
|           class R = void> | ||||
| struct output_iterator_helper | ||||
|   : incrementable<T | ||||
|   , boost::iterator<std::output_iterator_tag, V, D, P, R | ||||
|     > > {}; | ||||
| #endif | ||||
| template <class T, | ||||
|           class V, | ||||
|           class D = std::ptrdiff_t, | ||||
|           class P = V*, | ||||
|           class R = V&> | ||||
| struct forward_iterator_helper | ||||
|   : equality_comparable<T | ||||
|   : equality_comparable1<T | ||||
|   , incrementable<T | ||||
|   , dereferenceable<T,P | ||||
|   , boost::iterator<std::forward_iterator_tag,V,D,P,R | ||||
|   , dereferenceable<T, P | ||||
|   , boost::iterator<std::forward_iterator_tag, V, D, P, R | ||||
|     > > > > {}; | ||||
|  | ||||
| template <class T, | ||||
| @@ -525,12 +730,11 @@ template <class T, | ||||
|           class P = V*, | ||||
|           class R = V&> | ||||
| struct bidirectional_iterator_helper | ||||
|   : equality_comparable<T | ||||
|   , incrementable<T | ||||
|   , decrementable<T | ||||
|   , dereferenceable<T,P | ||||
|   , boost::iterator<std::bidirectional_iterator_tag,V,D,P,R | ||||
|     > > > > > {}; | ||||
|   : equality_comparable1<T | ||||
|   , unit_steppable<T | ||||
|   , dereferenceable<T, P | ||||
|   , boost::iterator<std::bidirectional_iterator_tag, V, D, P, R | ||||
|     > > > > {}; | ||||
|  | ||||
| template <class T, | ||||
|           class V,  | ||||
| @@ -538,22 +742,17 @@ template <class T, | ||||
|           class P = V*, | ||||
|           class R = V&> | ||||
| struct random_access_iterator_helper | ||||
|   : equality_comparable<T | ||||
|   , less_than_comparable<T | ||||
|   , incrementable<T | ||||
|   , decrementable<T | ||||
|   , dereferenceable<T,P | ||||
|   , addable2<T,D | ||||
|   , subtractable2<T,D | ||||
|   , indexable<T,D,R | ||||
|   , boost::iterator<std::random_access_iterator_tag,V,D,P,R | ||||
|     > > > > > > > > > | ||||
|   : totally_ordered1<T | ||||
|   , unit_steppable<T | ||||
|   , dereferenceable<T, P | ||||
|   , additive2<T, D | ||||
|   , indexable<T, D, R | ||||
|   , boost::iterator<std::random_access_iterator_tag, V, D, P, R | ||||
|     > > > > > > | ||||
| { | ||||
| #ifndef __BORLANDC__ | ||||
|   friend D requires_difference_operator(const T& x, const T& y) { | ||||
|     return x - y; | ||||
|   } | ||||
| #endif | ||||
| }; // random_access_iterator_helper | ||||
|  | ||||
| } // namespace boost | ||||
|   | ||||
| @@ -11,6 +11,9 @@ | ||||
| //  Classes appear in alphabetical order | ||||
|  | ||||
| //  Revision History | ||||
| //  21 May 01  checked_delete() and checked_array_delete() added (Beman Dawes, | ||||
| //             suggested by Dave Abrahams, generalizing idea from Vladimir Prus) | ||||
| //  21 May 01  made next() and prior() inline (Beman Dawes)   | ||||
| //  26 Jan 00  protected noncopyable destructor added (Miki Jovanovic) | ||||
| //  10 Dec 99  next() and prior() templates added (Dave Abrahams) | ||||
| //  30 Aug 99  moved cast templates to cast.hpp (Beman Dawes) | ||||
| @@ -22,12 +25,32 @@ | ||||
| #ifndef BOOST_UTILITY_HPP | ||||
| #define BOOST_UTILITY_HPP | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
| #include <cstddef>            // for size_t | ||||
| #include <utility>            // for std::pair | ||||
| #include <boost/config.hpp>        // broken compiler workarounds  | ||||
| #include <boost/static_assert.hpp>  | ||||
| #include <cstddef>                 // for size_t | ||||
| #include <utility>                 // for std::pair | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
| //  checked_delete() and checked_array_delete()  -----------------------------// | ||||
|  | ||||
|     // verify that types are complete for increased safety | ||||
|  | ||||
|     template< typename T > | ||||
|     inline void checked_delete(T * x) | ||||
|     { | ||||
|         BOOST_STATIC_ASSERT( sizeof(T) != 0 ); // assert type complete at point | ||||
|                                                // of instantiation | ||||
|         delete x; | ||||
|     } | ||||
|  | ||||
|     template< typename T > | ||||
|     inline void checked_array_delete(T  * x) | ||||
|     { | ||||
|         BOOST_STATIC_ASSERT( sizeof(T) != 0 ); // assert type complete at point | ||||
|                                                // of instantiation | ||||
|         delete [] x; | ||||
|     } | ||||
|  | ||||
| //  next() and prior() template functions  -----------------------------------// | ||||
|  | ||||
| @@ -41,10 +64,10 @@ namespace boost | ||||
|     //  Contributed by Dave Abrahams | ||||
|  | ||||
|     template <class T> | ||||
|     T next(T x) { return ++x; } | ||||
|     inline T next(T x) { return ++x; } | ||||
|  | ||||
|     template <class T> | ||||
|     T prior(T x) { return --x; } | ||||
|     inline T prior(T x) { return --x; } | ||||
|  | ||||
|  | ||||
| //  class noncopyable  -------------------------------------------------------// | ||||
|   | ||||
| @@ -422,7 +422,7 @@ a,b,c,d,e,f,g, | ||||
|     <hr> | ||||
|  | ||||
|     <p>Revised  | ||||
|     <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->28 Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14390" --> | ||||
|     <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->08 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14892" --> | ||||
|  | ||||
|  | ||||
|     <p>© Copyright Jeremy Siek and David Abrahams 2001. Permission to | ||||
|   | ||||
| @@ -29,8 +29,7 @@ int main(int, char*[]) | ||||
|  | ||||
|   // Example of using indirect_iterator_pair_generator | ||||
|  | ||||
|   typedef boost::indirect_iterator_pair_generator<char**, | ||||
|     char, char*, char&, const char*, const char&> PairGen; | ||||
|   typedef boost::indirect_iterator_pair_generator<char**, char> PairGen; | ||||
|  | ||||
|   char mutable_characters[N]; | ||||
|   char* pointers_to_mutable_chars[N]; | ||||
|   | ||||
| @@ -4,6 +4,8 @@ | ||||
| // "as is" without express or implied warranty, and with no claim as
 | ||||
| // to its suitability for any purpose.
 | ||||
| 
 | ||||
| // 27 June 2001 Jeremy Siek
 | ||||
| //     Upated for change in named params.
 | ||||
| // 8 Mar 2001   Jeremy Siek
 | ||||
| //     Initial checkin.
 | ||||
| 
 | ||||
| @@ -11,9 +13,6 @@ | ||||
| #include <boost/pending/iterator_tests.hpp> | ||||
| #include <boost/static_assert.hpp> | ||||
| 
 | ||||
| class bar { }; | ||||
| void foo(bar) { } | ||||
| 
 | ||||
| int | ||||
| main() | ||||
| { | ||||
| @@ -26,9 +25,8 @@ main() | ||||
| 
 | ||||
|   { | ||||
|     typedef boost::iterator_adaptor<my_iter, boost::default_iterator_policies, | ||||
|       boost::iterator_traits_generator | ||||
|       ::reference<dummyT> | ||||
|       ::iterator_category<std::input_iterator_tag> > iter_type; | ||||
|       boost::reference_is<dummyT>, | ||||
|       boost::iterator_category_is<std::input_iterator_tag> > iter_type; | ||||
| 
 | ||||
|     BOOST_STATIC_ASSERT((boost::is_same<iter_type::iterator_category*, | ||||
|        std::input_iterator_tag*>::value)); | ||||
| @@ -42,12 +40,11 @@ main() | ||||
|   { | ||||
|     typedef boost::iterator_adaptor<dummyT*, | ||||
|       boost::default_iterator_policies, | ||||
|       boost::iterator_traits_generator | ||||
|         ::value_type<dummyT> | ||||
|         ::reference<const dummyT&> | ||||
|         ::pointer<const dummyT*>  | ||||
|         ::iterator_category<std::forward_iterator_tag> | ||||
|         ::difference_type<std::ptrdiff_t> > adaptor_type; | ||||
|       boost::value_type_is<dummyT>, | ||||
|       boost::reference_is<const dummyT&>, | ||||
|       boost::pointer_is<const dummyT*>, | ||||
|       boost::iterator_category_is<std::forward_iterator_tag>, | ||||
|       boost::difference_type_is<std::ptrdiff_t> > adaptor_type; | ||||
| 
 | ||||
|     adaptor_type i(array); | ||||
| 
 | ||||
| @@ -21,9 +21,8 @@ main(int, char*[]) | ||||
|   int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; | ||||
|  | ||||
|   typedef std::binder1st< std::multiplies<int> > Function; | ||||
|   typedef boost::transform_iterator<Function, int*,  | ||||
|     boost::iterator<std::random_access_iterator_tag, int> | ||||
|   >::type doubling_iterator; | ||||
|   typedef boost::transform_iterator_generator<Function, int* | ||||
|     >::type doubling_iterator; | ||||
|  | ||||
|   doubling_iterator i(x, std::bind1st(std::multiplies<int>(), 2)), | ||||
|     i_end(x + sizeof(x)/sizeof(int), std::bind1st(std::multiplies<int>(), 2)); | ||||
|   | ||||
| @@ -9,6 +9,7 @@ | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
|  | ||||
| //  Revision History | ||||
| //  27 June 01 Updated to changes in named parameters. | ||||
| //  08 Mar 01 Moved indirect and transform tests to separate files. | ||||
| //            (Jeremy Siek) | ||||
| //  19 Feb 01 Take adavantage of improved iterator_traits to do more tests | ||||
| @@ -52,8 +53,7 @@ | ||||
| #include <boost/pending/iterator_tests.hpp> | ||||
| #include <boost/pending/integer_range.hpp> | ||||
| #include <boost/concept_archetype.hpp> | ||||
| #include <stdlib.h> | ||||
| #include <vector> | ||||
| #include <cstdlib> | ||||
| #include <deque> | ||||
| #include <set> | ||||
|  | ||||
| @@ -97,6 +97,9 @@ typedef std::deque<int> storage; | ||||
| typedef std::deque<int*> pointer_deque; | ||||
| typedef std::set<storage::iterator> iterator_set; | ||||
|  | ||||
| struct bar { }; | ||||
| void foo(bar) { } | ||||
|  | ||||
| int | ||||
| main() | ||||
| { | ||||
| @@ -306,12 +309,11 @@ main() | ||||
| #else | ||||
|     typedef boost::iterator_adaptor<boost::forward_iterator_archetype<dummyT>, | ||||
|       boost::default_iterator_policies, | ||||
|       boost::iterator_traits_generator | ||||
|         ::value_type<dummyT> | ||||
|         ::reference<const dummyT&> | ||||
|         ::pointer<const dummyT*>  | ||||
|         ::iterator_category<std::forward_iterator_tag> | ||||
|         ::difference_type<std::ptrdiff_t> > adaptor_type; | ||||
|       boost::value_type_is<dummyT>, | ||||
|       boost::reference_is<const dummyT&>, | ||||
|       boost::pointer_is<const dummyT*>, | ||||
|       boost::iterator_category_is<std::forward_iterator_tag>, | ||||
|       boost::difference_type_is<std::ptrdiff_t> > adaptor_type; | ||||
| #endif | ||||
|     adaptor_type i(forward_iter); | ||||
|     int zero = 0; | ||||
|   | ||||
| @@ -170,7 +170,8 @@ struct iterator_adaptor; | ||||
|         <td>The <tt>value_type</tt> of the resulting iterator, unless const. If | ||||
|         Value is <tt>const X</tt> the | ||||
|         <tt>value_type</tt> will be (<i>non-</i><tt>const</tt>) <tt>X</tt><a href= | ||||
|         "#1">[1]</a>.<br> | ||||
|         "#1">[1]</a>. If the <tt>value_type</tt> you wish to use is an abstract | ||||
|         base class see note <a href="#5">[5]</a>.<br> | ||||
|          <b>Default:</b> | ||||
|         <tt>std::iterator_traits<BaseType>::value_type</tt> <a href= | ||||
|         "#2">[2]</a> | ||||
| @@ -310,13 +311,13 @@ iterator_adaptor<foo_iterator, foo_policies, | ||||
|         <th>Required for Iterator Categories | ||||
|  | ||||
|       <tr> | ||||
|         <td><tt>dereference</tt>  | ||||
|         <td><tt>initialize</tt> | ||||
|  | ||||
|         <td>returns an element of the iterator's <tt>reference</tt> type | ||||
|          | ||||
|         <td><tt>*p</tt>, <tt>p[n]</tt> | ||||
|         <td>optionally modify base iterator during iterator construction | ||||
|  | ||||
|         <td rowspan="3"><a href= | ||||
|         <td>constructors | ||||
|  | ||||
|         <td rowspan="4"><a href= | ||||
|         "http://www.sgi.com/tech/stl/InputIterator.html">Input</a>/ <a href= | ||||
|         "http://www.sgi.com/tech/stl/OutputIterator.html">Output</a>/ <a href= | ||||
|         "http://www.sgi.com/tech/stl/ForwardIterator.html">Forward</a>/ <a | ||||
| @@ -325,6 +326,15 @@ iterator_adaptor<foo_iterator, foo_policies, | ||||
|         <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random | ||||
|         Access</a>  | ||||
|  | ||||
| 	   | ||||
|       <tr> | ||||
|         <td><tt>dereference</tt>  | ||||
|  | ||||
|         <td>returns an element of the iterator's <tt>reference</tt> type | ||||
|          | ||||
|         <td><tt>*p</tt>, <tt>p[n]</tt> | ||||
|  | ||||
|  | ||||
|       <tr> | ||||
|         <td><tt>equal</tt>  | ||||
|  | ||||
| @@ -404,6 +414,10 @@ iterator_adaptor<foo_iterator, foo_policies, | ||||
| <pre> | ||||
| struct <a name="default_iterator_policies">default_iterator_policies</a> | ||||
| { | ||||
|   template <class BaseType> | ||||
|   void initialize(BaseType&) | ||||
|     { } | ||||
|  | ||||
|   template <class Reference, class BaseType> | ||||
|   Reference dereference(type<Reference>, const BaseType& x) const | ||||
|     { return *x; } | ||||
| @@ -829,10 +843,24 @@ bool operator==(const iterator_adaptor<B1,P,V1,R1,P1,C,D>&, | ||||
|     returning a reference could cause serious memory problems due to the | ||||
|     reference being bound to a temporary object whose lifetime ends inside of | ||||
|     the <tt>operator[]</tt>. | ||||
|  | ||||
|     <p><a name="5">[5]</a> | ||||
|     The <tt>value_type</tt> of an iterator may not be | ||||
|     an abstract base class, however many common uses of iterators | ||||
|     never need the <tt>value_type</tt>, only the <tt>reference</tt> type. | ||||
|     If you wish to create such an iterator adaptor, use a dummy | ||||
|     type such as <tt>char</tt> for the <tt>Value</tt> parameter, | ||||
|     and use a reference to your abstract base class for | ||||
|     the <tt>Reference</tt> parameter. Note that such an iterator | ||||
|     does not fulfill the C++ standards requirements for a | ||||
|     <a href= "http://www.sgi.com/tech/stl/ForwardIterator.html"> | ||||
|     Forward Iterator</a>, so you will need to use a less restrictive | ||||
|     iterator category such as <tt>std::input_iterator_tag</tt>. | ||||
|  | ||||
|     <hr> | ||||
|  | ||||
|     <p>Revised  | ||||
|     <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->09 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14894" --> | ||||
|     <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->19 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14895" --> | ||||
|  | ||||
|  | ||||
|     <p>© Copyright Dave Abrahams and Jeremy Siek 2001. Permission to copy, | ||||
|   | ||||
| @@ -9,16 +9,25 @@ | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
|  | ||||
| //  Revision History | ||||
| //  29 May 01 Factored implementation, added comparison tests, use Test Tools | ||||
| //            library (Daryle Walker) | ||||
| //  12 Dec 99 Initial version with iterator operators (Jeremy Siek) | ||||
|  | ||||
| #include <string> | ||||
| #include <iostream> | ||||
| using namespace std; | ||||
| #define  BOOST_INCLUDE_MAIN | ||||
| #include <boost/test/test_tools.hpp>  // for main | ||||
|  | ||||
| #include <boost/operators.hpp> | ||||
| using namespace boost; | ||||
| #include <boost/config.hpp>     // for BOOST_STATIC_CONSTANT | ||||
| #include <boost/cstdlib.hpp>    // for boost::exit_success | ||||
| #include <boost/operators.hpp>  // for boost::random_access_iterator_helper | ||||
|  | ||||
| #include <cstddef>    // for std::ptrdiff_t, std::size_t | ||||
| #include <cstring>    // for std::strcmp | ||||
| #include <iostream>   // for std::cout (std::endl, ends, and flush indirectly) | ||||
| #include <string>     // for std::string | ||||
| #include <strstream>  // for std::ostrstream | ||||
|  | ||||
|  | ||||
| // Iterator test class | ||||
| template <class T, class R, class P> | ||||
| struct test_iter | ||||
|   : public boost::random_access_iterator_helper< | ||||
| @@ -29,7 +38,7 @@ struct test_iter | ||||
|   typedef std::ptrdiff_t Distance; | ||||
|  | ||||
| public: | ||||
|   test_iter(T* i) : _i(i) { } | ||||
|   explicit test_iter(T* i =0) : _i(i) { } | ||||
|   test_iter(const self& x) : _i(x._i) { } | ||||
|   self& operator=(const self& x) { _i = x._i; return *this; } | ||||
|   Reference operator*() const { return *_i; } | ||||
| @@ -43,127 +52,280 @@ public: | ||||
|     return x._i - y._i;  | ||||
|   } | ||||
| protected: | ||||
|   T* _i; | ||||
|   P _i; | ||||
| }; | ||||
|  | ||||
|  | ||||
| int | ||||
| main() | ||||
| // Iterator operator testing classes | ||||
| class test_opr_base | ||||
| { | ||||
|   string array[] = { "apple", "orange", "pear", "peach", "grape", "plum"  }; | ||||
|   { | ||||
|     test_iter<string,string&,string*> i = array,  | ||||
|       ie = array + sizeof(array)/sizeof(string); | ||||
| protected: | ||||
|     // Test data and types | ||||
|     BOOST_STATIC_CONSTANT( std::size_t, fruit_length = 6u ); | ||||
|     BOOST_STATIC_CONSTANT( std::size_t, scratch_length = 40u ); | ||||
|  | ||||
|     // Tests for all of the operators added by random_access_iterator_helper | ||||
|     typedef std::string  fruit_array_type[ fruit_length ]; | ||||
|     typedef char         scratch_array_type[ scratch_length ]; | ||||
|  | ||||
|     // test i++ | ||||
|     while (i != ie) | ||||
|       cout << *i++ << " "; | ||||
|     cout << endl; | ||||
|     i = array; | ||||
|     static  fruit_array_type    fruit; | ||||
|     static  scratch_array_type  scratch; | ||||
|  | ||||
|     // test i-- | ||||
|     while (ie != i) { | ||||
|       ie--; | ||||
|       cout << *ie << " "; | ||||
|     } | ||||
|     cout << endl; | ||||
|     ie = array + sizeof(array)/sizeof(string); | ||||
| };  // test_opr_base | ||||
|  | ||||
|     // test i->m | ||||
|     while (i != ie) { | ||||
|       cout << i->size() << " "; | ||||
|       ++i; | ||||
|     } | ||||
|     cout << endl; | ||||
|     i = array; | ||||
| template <typename T, typename R = T&, typename P = T*> | ||||
| class test_opr | ||||
|     : public test_opr_base | ||||
| { | ||||
|     typedef test_opr<T, R, P>  self_type; | ||||
|  | ||||
|     // test i + n | ||||
|     while (i < ie) { | ||||
|       cout << *i << " "; | ||||
|       i = i + 2; | ||||
|     } | ||||
|     cout << endl; | ||||
|     i = array; | ||||
| public: | ||||
|     // Types | ||||
|     typedef T  value_type; | ||||
|     typedef R  reference; | ||||
|     typedef P  pointer; | ||||
|  | ||||
|     // test n + i | ||||
|     while (i < ie) { | ||||
|       cout << *i << " "; | ||||
|       i = ptrdiff_t(2) + i; | ||||
|     } | ||||
|     cout << endl; | ||||
|     i = array; | ||||
|     typedef test_iter<T, R, P>  iter_type; | ||||
|  | ||||
|     // test i - n | ||||
|     while (ie > i) { | ||||
|       ie = ie - 2; | ||||
|       cout << *ie << " "; | ||||
|     } | ||||
|     cout << endl; | ||||
|     ie = array + sizeof(array)/sizeof(string); | ||||
|     // Test controller | ||||
|     static  void  master_test( char const name[] ); | ||||
|  | ||||
|     // test i[n] | ||||
|     for (std::size_t j = 0; j < sizeof(array)/sizeof(string); ++j) | ||||
|       cout << i[j] << " "; | ||||
|     cout << endl; | ||||
|   } | ||||
|   { | ||||
|     test_iter<string, const string&, const string*> i = array,  | ||||
|       ie = array + sizeof(array)/sizeof(string); | ||||
| private: | ||||
|     // Test data | ||||
|     static  iter_type const  fruit_begin, fruit_end; | ||||
|  | ||||
|     // Tests for all of the operators added by random_access_iterator_helper | ||||
|     // Test parts | ||||
|     static  void  post_increment_test(); | ||||
|     static  void  post_decrement_test(); | ||||
|     static  void  indirect_referral_test(); | ||||
|     static  void  offset_addition_test(); | ||||
|     static  void  reverse_offset_addition_test(); | ||||
|     static  void  offset_subtraction_test(); | ||||
|     static  void  comparison_test(); | ||||
|     static  void  indexing_test(); | ||||
|  | ||||
|     // test i++ | ||||
|     while (i != ie) | ||||
|       cout << *i++ << " "; | ||||
|     cout << endl; | ||||
|     i = array; | ||||
| };  // test_opr | ||||
|  | ||||
|     // test i-- | ||||
|     while (ie != i) { | ||||
|       ie--; | ||||
|       cout << *ie << " "; | ||||
|     } | ||||
|     cout << endl; | ||||
|     ie = array + sizeof(array)/sizeof(string); | ||||
|  | ||||
|     // test i->m | ||||
|     while (i != ie) { | ||||
|       cout << i->size() << " "; | ||||
|       ++i; | ||||
|     } | ||||
|     cout << endl; | ||||
|     i = array; | ||||
| // Class-static data definitions | ||||
| test_opr_base::fruit_array_type | ||||
|  test_opr_base::fruit = { "apple", "orange", "pear", "peach", "grape", "plum" }; | ||||
|  | ||||
|     // test i + n | ||||
|     while (i < ie) { | ||||
|       cout << *i << " "; | ||||
|       i = i + 2; | ||||
|     } | ||||
|     cout << endl; | ||||
|     i = array; | ||||
| test_opr_base::scratch_array_type | ||||
|  test_opr_base::scratch = ""; | ||||
|  | ||||
|     // test n + i | ||||
|     while (i < ie) { | ||||
|       cout << *i << " "; | ||||
|       i = ptrdiff_t(2) + i; | ||||
|     } | ||||
|     cout << endl; | ||||
|     i = array; | ||||
| template <typename T, typename R, typename P> | ||||
| typename test_opr<T, R, P>::iter_type const | ||||
|  test_opr<T, R, P>::fruit_begin( fruit ); | ||||
|  | ||||
|     // test i - n | ||||
|     while (ie > i) { | ||||
|       ie = ie - 2; | ||||
|       cout << *ie << " "; | ||||
|     } | ||||
|     cout << endl; | ||||
|     ie = array + sizeof(array)/sizeof(string); | ||||
| template <typename T, typename R, typename P> | ||||
| typename test_opr<T, R, P>::iter_type const | ||||
|  test_opr<T, R, P>::fruit_end( fruit + fruit_length ); | ||||
|  | ||||
|     // test i[n] | ||||
|     for (std::size_t j = 0; j < sizeof(array)/sizeof(string); ++j) | ||||
|       cout << i[j] << " "; | ||||
|     cout << endl; | ||||
|   } | ||||
|   return 0; | ||||
|  | ||||
| // Main testing function | ||||
| int | ||||
| test_main( int , char * [] ) | ||||
| { | ||||
|     using std::string; | ||||
|  | ||||
|     typedef test_opr<string, string &, string *>              test1_type; | ||||
|     typedef test_opr<string, string const &, string const *>  test2_type; | ||||
|  | ||||
|     test1_type::master_test( "non-const string" ); | ||||
|     test2_type::master_test( "const string" ); | ||||
|  | ||||
|     return boost::exit_success; | ||||
| } | ||||
|  | ||||
| // Tests for all of the operators added by random_access_iterator_helper | ||||
| template <typename T, typename R, typename P> | ||||
| void | ||||
| test_opr<T, R, P>::master_test | ||||
| ( | ||||
|     char const  name[] | ||||
| ) | ||||
| { | ||||
|     std::cout << "Doing test run for " << name << '.' << std::endl; | ||||
|  | ||||
|     post_increment_test(); | ||||
|     post_decrement_test(); | ||||
|     indirect_referral_test(); | ||||
|     offset_addition_test(); | ||||
|     reverse_offset_addition_test(); | ||||
|     offset_subtraction_test(); | ||||
|     comparison_test(); | ||||
|     indexing_test(); | ||||
| } | ||||
|  | ||||
| // Test post-increment | ||||
| template <typename T, typename R, typename P> | ||||
| void | ||||
| test_opr<T, R, P>::post_increment_test | ||||
| ( | ||||
| ) | ||||
| { | ||||
|     std::cout << "\tDoing post-increment test." << std::endl; | ||||
|  | ||||
|     std::ostrstream  oss( scratch, scratch_length ); | ||||
|     for ( iter_type i = fruit_begin ; i != fruit_end ; ) | ||||
|     { | ||||
|         oss << *i++ << ' '; | ||||
|     } | ||||
|  | ||||
|     oss << std::ends; | ||||
|     BOOST_TEST( std::strcmp(oss.str(), "apple orange pear peach grape plum ") | ||||
|      == 0 ); | ||||
| } | ||||
|  | ||||
| // Test post-decrement | ||||
| template <typename T, typename R, typename P> | ||||
| void | ||||
| test_opr<T, R, P>::post_decrement_test | ||||
| ( | ||||
| ) | ||||
| { | ||||
|     std::cout << "\tDoing post-decrement test." << std::endl; | ||||
|  | ||||
|     std::ostrstream  oss( scratch, scratch_length ); | ||||
|     for ( iter_type i = fruit_end ; i != fruit_begin ; ) | ||||
|     { | ||||
|         i--; | ||||
|         oss << *i << ' '; | ||||
|     } | ||||
|  | ||||
|     oss << std::ends; | ||||
|     BOOST_TEST( std::strcmp(oss.str(), "plum grape peach pear orange apple ") | ||||
|      == 0 ); | ||||
| } | ||||
|  | ||||
| // Test indirect structure referral | ||||
| template <typename T, typename R, typename P> | ||||
| void | ||||
| test_opr<T, R, P>::indirect_referral_test | ||||
| ( | ||||
| ) | ||||
| { | ||||
|     std::cout << "\tDoing indirect reference test." << std::endl; | ||||
|  | ||||
|     std::ostrstream  oss( scratch, scratch_length ); | ||||
|     for ( iter_type i = fruit_begin ; i != fruit_end ; ++i ) | ||||
|     { | ||||
|         oss << i->size() << ' '; | ||||
|     } | ||||
|  | ||||
|     oss << std::ends; | ||||
|     BOOST_TEST( std::strcmp(oss.str(), "5 6 4 5 5 4 ") == 0 ); | ||||
| } | ||||
|  | ||||
| // Test offset addition | ||||
| template <typename T, typename R, typename P> | ||||
| void | ||||
| test_opr<T, R, P>::offset_addition_test | ||||
| ( | ||||
| ) | ||||
| { | ||||
|     std::cout << "\tDoing offset addition test." << std::endl; | ||||
|  | ||||
|     std::ptrdiff_t const  two = 2; | ||||
|     std::ostrstream       oss( scratch, scratch_length ); | ||||
|     for ( iter_type i = fruit_begin ; i != fruit_end ; i = i + two ) | ||||
|     { | ||||
|         oss << *i << ' '; | ||||
|     } | ||||
|  | ||||
|     oss << std::ends; | ||||
|     BOOST_TEST( std::strcmp(oss.str(), "apple pear grape ") == 0 ); | ||||
| } | ||||
|  | ||||
| // Test offset addition, in reverse order | ||||
| template <typename T, typename R, typename P> | ||||
| void | ||||
| test_opr<T, R, P>::reverse_offset_addition_test | ||||
| ( | ||||
| ) | ||||
| { | ||||
|     std::cout << "\tDoing reverse offset addition test." << std::endl; | ||||
|  | ||||
|     std::ptrdiff_t const  two = 2; | ||||
|     std::ostrstream       oss( scratch, scratch_length ); | ||||
|     for ( iter_type i = fruit_begin ; i != fruit_end ; i = two + i ) | ||||
|     { | ||||
|         oss << *i << ' '; | ||||
|     } | ||||
|  | ||||
|     oss << std::ends; | ||||
|     BOOST_TEST( std::strcmp(oss.str(), "apple pear grape ") == 0 ); | ||||
| } | ||||
|  | ||||
| // Test offset subtraction | ||||
| template <typename T, typename R, typename P> | ||||
| void | ||||
| test_opr<T, R, P>::offset_subtraction_test | ||||
| ( | ||||
| ) | ||||
| { | ||||
|     std::cout << "\tDoing offset subtraction test." << std::endl; | ||||
|  | ||||
|     std::ptrdiff_t const  two = 2; | ||||
|     std::ostrstream       oss( scratch, scratch_length ); | ||||
|     for ( iter_type i = fruit_end ; fruit_begin < i ; ) | ||||
|     { | ||||
|         i = i - two; | ||||
|         if ( (fruit_begin < i) || (fruit_begin == i) ) | ||||
|         { | ||||
|             oss << *i << ' '; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     oss << std::ends; | ||||
|     BOOST_TEST( std::strcmp(oss.str(), "grape pear apple ") == 0 ); | ||||
| } | ||||
|  | ||||
| // Test comparisons | ||||
| template <typename T, typename R, typename P> | ||||
| void | ||||
| test_opr<T, R, P>::comparison_test | ||||
| ( | ||||
| ) | ||||
| { | ||||
|     using std::cout; | ||||
|     using std::ptrdiff_t; | ||||
|  | ||||
|     cout << "\tDoing comparison tests.\n\t\tPass:"; | ||||
|  | ||||
|     for ( iter_type i = fruit_begin ; i != fruit_end ; ++i ) | ||||
|     { | ||||
|         ptrdiff_t const  i_offset = i - fruit_begin; | ||||
|  | ||||
|         cout << ' ' << *i << std::flush; | ||||
|         for ( iter_type j = fruit_begin ; j != fruit_end ; ++j ) | ||||
|         { | ||||
|             ptrdiff_t const  j_offset = j - fruit_begin; | ||||
|  | ||||
|             BOOST_TEST( (i != j) == (i_offset != j_offset) ); | ||||
|             BOOST_TEST( (i > j) == (i_offset > j_offset) ); | ||||
|             BOOST_TEST( (i <= j) == (i_offset <= j_offset) ); | ||||
|             BOOST_TEST( (i >= j) == (i_offset >= j_offset) ); | ||||
|         } | ||||
|     } | ||||
|     cout << std::endl; | ||||
| } | ||||
|  | ||||
| // Test indexing | ||||
| template <typename T, typename R, typename P> | ||||
| void | ||||
| test_opr<T, R, P>::indexing_test | ||||
| ( | ||||
| ) | ||||
| { | ||||
|     std::cout << "\tDoing indexing test." << std::endl; | ||||
|  | ||||
|     std::ostrstream  oss( scratch, scratch_length ); | ||||
|     for ( std::size_t k = 0u ; k < fruit_length ; ++k ) | ||||
|     { | ||||
|         oss << fruit_begin[ k ] << ' '; | ||||
|     } | ||||
|  | ||||
|     oss << std::ends; | ||||
|     BOOST_TEST( std::strcmp(oss.str(), "apple orange pear peach grape plum ") | ||||
|      == 0 ); | ||||
| } | ||||
|   | ||||
							
								
								
									
										1513
									
								
								operators.htm
									
									
									
									
									
								
							
							
						
						
									
										1513
									
								
								operators.htm
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -8,18 +8,26 @@ | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
|  | ||||
| //  Revision History | ||||
| //  20 May 01 Output progress messages.  Added tests for new operator | ||||
| //            templates.  Updated random number generator.  Changed tests to | ||||
| //            use Boost Test Tools library.  (Daryle Walker) | ||||
| //  04 Jun 00 Added regression test for a bug I found (David Abrahams) | ||||
| //  17 Jun 00 Fix for broken compilers (Aleksey Gurtovoy) | ||||
| //  ?? ??? 00 Major update to randomly test all one- and two- argument forms by | ||||
| //            wrapping integral types and comparing the results of operations to | ||||
| //            the results for the raw types (David Abrahams) | ||||
| //            wrapping integral types and comparing the results of operations | ||||
| //            to the results for the raw types (David Abrahams) | ||||
| //  12 Dec 99 Minor update, output confirmation message. | ||||
| //  15 Nov 99 Initial version | ||||
|  | ||||
| #include <boost/operators.hpp> | ||||
| #include <cassert> | ||||
| #include <iostream> | ||||
| #include <boost/min_rand.hpp> | ||||
| #define BOOST_INCLUDE_MAIN | ||||
|  | ||||
| #include <boost/config.hpp>                      // for BOOST_MSVC | ||||
| #include <boost/cstdlib.hpp>                     // for boost::exit_success | ||||
| #include <boost/operators.hpp>                   // for the tested items | ||||
| #include <boost/random/linear_congruential.hpp>  // for boost::minstd_rand | ||||
| #include <boost/test/test_tools.hpp>             // for main | ||||
|  | ||||
| #include <iostream>  // for std::cout (std::endl indirectly) | ||||
|  | ||||
|  | ||||
| namespace | ||||
| @@ -28,14 +36,18 @@ namespace | ||||
|     int true_value(int x) { return x; } | ||||
|     long true_value(long x) { return x; } | ||||
|     signed char true_value(signed char x) { return x; } | ||||
|     short true_value(short x) { return x; } | ||||
|     unsigned int true_value(unsigned int x) { return x; } | ||||
|     unsigned long true_value(unsigned long x) { return x; } | ||||
|     unsigned char true_value(unsigned char x) { return x; } | ||||
|     unsigned short true_value(unsigned short x) { return x; } | ||||
|  | ||||
|     // The use of operators<> here tended to obscure interactions with certain | ||||
|     // compiler bugs | ||||
|     // The use of operators<> here tended to obscure | ||||
|     // interactions with certain compiler bugs | ||||
|     template <class T> | ||||
|     class Wrapped1 : boost::operators<Wrapped1<T> > | ||||
|     class Wrapped1 | ||||
|         : boost::operators<Wrapped1<T> > | ||||
|         , boost::shiftable<Wrapped1<T> > | ||||
|     { | ||||
|     public: | ||||
|         explicit Wrapped1( T v = T() ) : _value(v) {} | ||||
| @@ -60,6 +72,10 @@ namespace | ||||
|           { _value &= x._value; return *this; } | ||||
|         Wrapped1& operator^=(const Wrapped1& x) | ||||
|           { _value ^= x._value; return *this; } | ||||
|         Wrapped1& operator<<=(const Wrapped1& x) | ||||
|           { _value <<= x._value; return *this; } | ||||
|         Wrapped1& operator>>=(const Wrapped1& x) | ||||
|           { _value >>= x._value; return *this; } | ||||
|         Wrapped1& operator++()               { ++_value; return *this; } | ||||
|         Wrapped1& operator--()               { --_value; return *this; } | ||||
|          | ||||
| @@ -70,9 +86,11 @@ namespace | ||||
|     T true_value(Wrapped1<T> x) { return x.value(); }     | ||||
|  | ||||
|     template <class T, class U> | ||||
|     class Wrapped2 : | ||||
|         boost::operators<Wrapped2<T, U> >, | ||||
|         boost::operators2<Wrapped2<T, U>, U> | ||||
|     class Wrapped2 | ||||
|         : boost::operators<Wrapped2<T, U> > | ||||
|         , boost::operators2<Wrapped2<T, U>, U> | ||||
|         , boost::shiftable1<Wrapped2<T, U> | ||||
|         , boost::shiftable2<Wrapped2<T, U>, U > > | ||||
|     { | ||||
|     public: | ||||
|         explicit Wrapped2( T v = T() ) : _value(v) {} | ||||
| @@ -97,6 +115,10 @@ namespace | ||||
|           { _value &= x._value; return *this; } | ||||
|         Wrapped2& operator^=(const Wrapped2& x) | ||||
|           { _value ^= x._value; return *this; } | ||||
|         Wrapped2& operator<<=(const Wrapped2& x) | ||||
|           { _value <<= x._value; return *this; } | ||||
|         Wrapped2& operator>>=(const Wrapped2& x) | ||||
|           { _value >>= x._value; return *this; } | ||||
|         Wrapped2& operator++()                { ++_value; return *this; } | ||||
|         Wrapped2& operator--()                { --_value; return *this; } | ||||
|           | ||||
| @@ -111,6 +133,8 @@ namespace | ||||
|         Wrapped2& operator|=(U u) { _value |= u; return *this; } | ||||
|         Wrapped2& operator&=(U u) { _value &= u; return *this; } | ||||
|         Wrapped2& operator^=(U u) { _value ^= u; return *this; } | ||||
|         Wrapped2& operator<<=(U u) { _value <<= u; return *this; } | ||||
|         Wrapped2& operator>>=(U u) { _value >>= u; return *this; } | ||||
|  | ||||
|     private: | ||||
|         T _value; | ||||
| @@ -118,203 +142,268 @@ namespace | ||||
|     template <class T, class U> | ||||
|     T true_value(Wrapped2<T,U> x) { return x.value(); } | ||||
|      | ||||
|     template <class T> | ||||
|     class Wrapped3 | ||||
|         : boost::equivalent<Wrapped3<T> > | ||||
|         , boost::partially_ordered<Wrapped3<T> > | ||||
|         , boost::equality_comparable<Wrapped3<T> > | ||||
|     { | ||||
|     public: | ||||
|         explicit Wrapped3( T v = T() ) : _value(v) {} | ||||
|         T value() const { return _value; } | ||||
|  | ||||
|         bool operator<(const Wrapped3& x) const { return _value < x._value; } | ||||
|          | ||||
|     private: | ||||
|         T _value; | ||||
|     }; | ||||
|     template <class T> | ||||
|     T true_value(Wrapped3<T> x) { return x.value(); }     | ||||
|  | ||||
|     template <class T, class U> | ||||
|     class Wrapped4 | ||||
|         : boost::equality_comparable1<Wrapped4<T, U> | ||||
|         , boost::equivalent1<Wrapped4<T, U> | ||||
|         , boost::partially_ordered1<Wrapped4<T, U> > > > | ||||
|         , boost::partially_ordered2<Wrapped4<T, U>, U | ||||
|         , boost::equivalent2<Wrapped4<T, U>, U | ||||
|         , boost::equality_comparable2<Wrapped4<T, U>, U> > > | ||||
|     { | ||||
|     public: | ||||
|         explicit Wrapped4( T v = T() ) : _value(v) {} | ||||
|         T value() const { return _value; } | ||||
|  | ||||
|         bool operator<(const Wrapped4& x) const { return _value < x._value; } | ||||
|           | ||||
|         bool operator<(U u) const { return _value < u; } | ||||
|         bool operator>(U u) const { return _value > u; } | ||||
|  | ||||
|     private: | ||||
|         T _value; | ||||
|     }; | ||||
|     template <class T, class U> | ||||
|     T true_value(Wrapped4<T,U> x) { return x.value(); } | ||||
|      | ||||
|     //  MyInt uses only the single template-argument form of all_operators<> | ||||
|     typedef Wrapped1<int> MyInt; | ||||
|  | ||||
|     typedef Wrapped2<long, long> MyLong; | ||||
|  | ||||
|     typedef Wrapped3<signed char> MyChar; | ||||
|  | ||||
|     typedef Wrapped4<short, short> MyShort; | ||||
|  | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void sanity_check(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         assert(true_value(y1) == true_value(y2)); | ||||
|         assert(true_value(x1) == true_value(x2)); | ||||
|         BOOST_TEST( true_value(y1) == true_value(y2) ); | ||||
|         BOOST_TEST( true_value(x1) == true_value(x2) ); | ||||
|     } | ||||
|  | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_less_than_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         assert((x1 < y1) == (x2 < y2)); | ||||
|         assert((x1 <= y1) == (x2 <= y2)); | ||||
|         assert((x1 >= y1) == (x2 >= y2)); | ||||
|         assert((x1 > y1) == (x2 > y2)); | ||||
|         BOOST_TEST( (x1 < y1) == (x2 < y2) ); | ||||
|         BOOST_TEST( (x1 <= y1) == (x2 <= y2) ); | ||||
|         BOOST_TEST( (x1 >= y1) == (x2 >= y2) ); | ||||
|         BOOST_TEST( (x1 > y1) == (x2 > y2) ); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_less_than_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         test_less_than_comparable_aux(x1, y1, x2, y2); | ||||
|         test_less_than_comparable_aux(y1, x1, y2, x2); | ||||
|         sanity_check( x1, y1, x2, y2 ); | ||||
|         test_less_than_comparable_aux( x1, y1, x2, y2 ); | ||||
|         test_less_than_comparable_aux( y1, x1, y2, x2 ); | ||||
|     } | ||||
|  | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_equality_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         assert((x1 == y1) == (x2 == y2)); | ||||
|         assert((x1 != y1) == (x2 != y2)); | ||||
|         BOOST_TEST( (x1 == y1) == (x2 == y2) ); | ||||
|         BOOST_TEST( (x1 != y1) == (x2 != y2) ); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_equality_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         test_equality_comparable_aux(x1, y1, x2, y2); | ||||
|         test_equality_comparable_aux(y1, x1, y2, x2); | ||||
|         sanity_check( x1, y1, x2, y2 ); | ||||
|         test_equality_comparable_aux( x1, y1, x2, y2 ); | ||||
|         test_equality_comparable_aux( y1, x1, y2, x2 ); | ||||
|     } | ||||
|  | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_multipliable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         assert((x1 * y1).value() == (x2 * y2)); | ||||
|         BOOST_TEST( (x1 * y1).value() == (x2 * y2) ); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_multipliable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         test_multipliable_aux(x1, y1, x2, y2); | ||||
|         test_multipliable_aux(y1, x1, y2, x2); | ||||
|         sanity_check( x1, y1, x2, y2 ); | ||||
|         test_multipliable_aux( x1, y1, x2, y2 ); | ||||
|         test_multipliable_aux( y1, x1, y2, x2 ); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_addable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         assert((x1 + y1).value() == (x2 + y2)); | ||||
|         BOOST_TEST( (x1 + y1).value() == (x2 + y2) ); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_addable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         test_addable_aux(x1, y1, x2, y2); | ||||
|         test_addable_aux(y1, x1, y2, x2); | ||||
|         sanity_check( x1, y1, x2, y2 ); | ||||
|         test_addable_aux( x1, y1, x2, y2 ); | ||||
|         test_addable_aux( y1, x1, y2, x2 ); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_subtractable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         assert((x1 - y1).value() == x2 - y2); | ||||
|         sanity_check( x1, y1, x2, y2 ); | ||||
|         BOOST_TEST( (x1 - y1).value() == (x2 - y2) ); | ||||
|     } | ||||
|  | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_dividable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         if (y2 != 0) | ||||
|             assert((x1 / y1).value() == x2 / y2); | ||||
|         sanity_check( x1, y1, x2, y2 ); | ||||
|         if ( y2 != 0 ) | ||||
|             BOOST_TEST( (x1 / y1).value() == (x2 / y2) ); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_modable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         if (y2 != 0) | ||||
|             assert((x1 / y1).value() == x2 / y2); | ||||
|         sanity_check( x1, y1, x2, y2 ); | ||||
|         if ( y2 != 0 ) | ||||
|             BOOST_TEST( (x1 % y1).value() == (x2 % y2) ); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_xorable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         assert((x1 ^ y1).value() == (x2 ^ y2)); | ||||
|         BOOST_TEST( (x1 ^ y1).value() == (x2 ^ y2) ); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_xorable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         test_xorable_aux(x1, y1, x2, y2); | ||||
|         test_xorable_aux(y1, x1, y2, x2); | ||||
|         sanity_check( x1, y1, x2, y2 ); | ||||
|         test_xorable_aux( x1, y1, x2, y2 ); | ||||
|         test_xorable_aux( y1, x1, y2, x2 ); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_andable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         assert((x1 & y1).value() == (x2 & y2)); | ||||
|         BOOST_TEST( (x1 & y1).value() == (x2 & y2) ); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_andable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         test_andable_aux(x1, y1, x2, y2); | ||||
|         test_andable_aux(y1, x1, y2, x2); | ||||
|         sanity_check( x1, y1, x2, y2 ); | ||||
|         test_andable_aux( x1, y1, x2, y2 ); | ||||
|         test_andable_aux( y1, x1, y2, x2 ); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_orable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         assert((x1 | y1).value() == (x2 | y2)); | ||||
|         BOOST_TEST( (x1 | y1).value() == (x2 | y2) ); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_orable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         test_orable_aux(x1, y1, x2, y2); | ||||
|         test_orable_aux(y1, x1, y2, x2); | ||||
|         sanity_check( x1, y1, x2, y2 ); | ||||
|         test_orable_aux( x1, y1, x2, y2 ); | ||||
|         test_orable_aux( y1, x1, y2, x2 ); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_left_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check( x1, y1, x2, y2 ); | ||||
|         BOOST_TEST( (x1 << y1).value() == (x2 << y2) ); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_right_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check( x1, y1, x2, y2 ); | ||||
|         BOOST_TEST( (x1 >> y1).value() == (x2 >> y2) ); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class X2> | ||||
|     void test_incrementable(X1 x1, X2 x2) | ||||
|     { | ||||
|         sanity_check(x1, x1, x2, x2); | ||||
|         assert(x1++.value() == x2++); | ||||
|         assert(x1.value() == x2); | ||||
|         sanity_check( x1, x1, x2, x2 ); | ||||
|         BOOST_TEST( (x1++).value() == x2++ ); | ||||
|         BOOST_TEST( x1.value() == x2 ); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class X2> | ||||
|     void test_decrementable(X1 x1, X2 x2) | ||||
|     { | ||||
|         sanity_check(x1, x1, x2, x2); | ||||
|         assert(x1--.value() == x2--); | ||||
|         assert(x1.value() == x2); | ||||
|         sanity_check( x1, x1, x2, x2 ); | ||||
|         BOOST_TEST( (x1--).value() == x2-- ); | ||||
|         BOOST_TEST( x1.value() == x2 ); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_all(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         test_less_than_comparable(x1, y1, x2, y2); | ||||
|         test_equality_comparable(x1, y1, x2, y2); | ||||
|         test_multipliable(x1, y1, x2, y2); | ||||
|         test_addable(x1, y1, x2, y2); | ||||
|         test_subtractable(x1, y1, x2, y2); | ||||
|         test_dividable(x1, y1, x2, y2); | ||||
|         test_modable(x1, y1, x2, y2); | ||||
|         test_xorable(x1, y1, x2, y2); | ||||
|         test_andable(x1, y1, x2, y2); | ||||
|         test_orable(x1, y1, x2, y2); | ||||
|         test_incrementable(x1, x2); | ||||
|         test_decrementable(x1, x2); | ||||
|         test_less_than_comparable( x1, y1, x2, y2 ); | ||||
|         test_equality_comparable( x1, y1, x2, y2 ); | ||||
|         test_multipliable( x1, y1, x2, y2 ); | ||||
|         test_addable( x1, y1, x2, y2 ); | ||||
|         test_subtractable( x1, y1, x2, y2 ); | ||||
|         test_dividable( x1, y1, x2, y2 ); | ||||
|         test_modable( x1, y1, x2, y2 ); | ||||
|         test_xorable( x1, y1, x2, y2 ); | ||||
|         test_andable( x1, y1, x2, y2 ); | ||||
|         test_orable( x1, y1, x2, y2 ); | ||||
|         test_left_shiftable( x1, y1, x2, y2 ); | ||||
|         test_right_shiftable( x1, y1, x2, y2 ); | ||||
|         test_incrementable( x1, x2 ); | ||||
|         test_decrementable( x1, x2 ); | ||||
|     } | ||||
|      | ||||
|     template <class Big, class Small> | ||||
|     struct tester | ||||
|     { | ||||
|         void operator()(boost::min_rand& randomizer) const | ||||
|         void operator()(boost::minstd_rand& randomizer) const | ||||
|         { | ||||
|             Big b1 = Big(randomizer()); | ||||
|             Big b2 = Big(randomizer()); | ||||
|             Small s = Small(randomizer()); | ||||
|             Big    b1 = Big( randomizer() ); | ||||
|             Big    b2 = Big( randomizer() ); | ||||
|             Small  s = Small( randomizer() ); | ||||
|              | ||||
|             test_all(Wrapped1<Big>(b1), Wrapped1<Big>(b2), b1, b2); | ||||
|             test_all(Wrapped2<Big, Small>(b1), s, b1, s); | ||||
|             test_all( Wrapped1<Big>(b1), Wrapped1<Big>(b2), b1, b2 ); | ||||
|             test_all( Wrapped2<Big, Small>(b1), s, b1, s ); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     // added as a regression test. We had a bug which this uncovered. | ||||
|     struct Point | ||||
|         : boost::addable<Point, | ||||
|         boost::subtractable<Point> > | ||||
|         : boost::addable<Point | ||||
|         , boost::subtractable<Point> > | ||||
|     { | ||||
|         Point( int h, int v ) : h(h), v(v) {} | ||||
|         Point() :h(0), v(0) {} | ||||
|         const Point& operator+=( const Point& rhs ) { h += rhs.h; v += rhs.v; return *this; } | ||||
|         const Point& operator-=( const Point& rhs ) { h -= rhs.h; v -= rhs.v; return *this; } | ||||
|         const Point& operator+=( const Point& rhs ) | ||||
|             { h += rhs.h; v += rhs.v; return *this; } | ||||
|         const Point& operator-=( const Point& rhs ) | ||||
|             { h -= rhs.h; v -= rhs.v; return *this; } | ||||
|  | ||||
|         int h; | ||||
|         int v; | ||||
|     }; | ||||
|  | ||||
| } // unnamed namespace | ||||
|  | ||||
|  | ||||
| @@ -340,20 +429,25 @@ template Wrapped2<unsigned long, unsigned char>; | ||||
| template Wrapped2<unsigned long, unsigned long>; | ||||
| #endif | ||||
|  | ||||
| #ifdef NDEBUG | ||||
| #error This program is pointless when NDEBUG disables assert()! | ||||
| #endif | ||||
| #define PRIVATE_EXPR_TEST(e, t)  BOOST_TEST( ((e), (t)) ) | ||||
|  | ||||
| int main() | ||||
|  | ||||
| int | ||||
| test_main( int , char * [] ) | ||||
| { | ||||
|     using std::cout; | ||||
|     using std::endl; | ||||
|  | ||||
|     // Regression test. | ||||
|     Point x; | ||||
|     x = x + Point(3, 4); | ||||
|     x = x - Point(3, 4); | ||||
|      | ||||
|     cout << "Created point, and operated on it." << endl; | ||||
|      | ||||
|     for (int n = 0; n < 10000; ++n) | ||||
|     { | ||||
|         boost::min_rand r; | ||||
|         boost::minstd_rand r; | ||||
|         tester<long, int>()(r); | ||||
|         tester<long, signed char>()(r); | ||||
|         tester<long, long>()(r); | ||||
| @@ -367,115 +461,197 @@ int main() | ||||
|         tester<unsigned int, unsigned char>()(r); | ||||
|     } | ||||
|      | ||||
|     cout << "Did random tester loop." << endl; | ||||
|  | ||||
|     MyInt i1(1); | ||||
|     MyInt i2(2); | ||||
|     MyInt i; | ||||
|  | ||||
|     assert( i1.value() == 1 ); | ||||
|     assert( i2.value() == 2 ); | ||||
|     assert( i.value() == 0 ); | ||||
|     BOOST_TEST( i1.value() == 1 ); | ||||
|     BOOST_TEST( i2.value() == 2 ); | ||||
|     BOOST_TEST( i.value() == 0 ); | ||||
|  | ||||
|     i = i2; | ||||
|     assert( i.value() == 2 ); | ||||
|     assert( i2 == i ); | ||||
|     assert( i1 != i2 ); | ||||
|     assert( i1 <  i2 ); | ||||
|     assert( i1 <= i2 ); | ||||
|     assert( i <= i2 ); | ||||
|     assert( i2 >  i1 ); | ||||
|     assert( i2 >= i1 ); | ||||
|     assert( i2 >= i ); | ||||
|     cout << "Created MyInt objects.\n"; | ||||
|  | ||||
|     i = i1 + i2; assert( i.value() == 3 ); | ||||
|     i = i + i2; assert( i.value() == 5 ); | ||||
|     i = i - i1; assert( i.value() == 4 ); | ||||
|     i = i * i2; assert( i.value() == 8 ); | ||||
|     i = i / i2; assert( i.value() == 4 ); | ||||
|     i = i % (i - i1); assert( i.value() == 1 ); | ||||
|     i = i2 + i2; assert( i.value() == 4 ); | ||||
|     i = i1 | i2 | i; assert( i.value() == 7 ); | ||||
|     i = i & i2; assert( i.value() == 2 ); | ||||
|     i = i + i1; assert( i.value() == 3 ); | ||||
|     i = i ^ i1; assert( i.value() == 2 ); | ||||
|     i = (i+i1)*(i2|i1); assert( i.value() == 9 ); | ||||
|     PRIVATE_EXPR_TEST( (i = i2), (i.value() == 2) ); | ||||
|  | ||||
|     BOOST_TEST( i2 == i ); | ||||
|     BOOST_TEST( i1 != i2 ); | ||||
|     BOOST_TEST( i1 <  i2 ); | ||||
|     BOOST_TEST( i1 <= i2 ); | ||||
|     BOOST_TEST( i <= i2 ); | ||||
|     BOOST_TEST( i2 >  i1 ); | ||||
|     BOOST_TEST( i2 >= i1 ); | ||||
|     BOOST_TEST( i2 >= i ); | ||||
|  | ||||
|     PRIVATE_EXPR_TEST( (i = i1 + i2), (i.value() == 3) ); | ||||
|     PRIVATE_EXPR_TEST( (i = i + i2), (i.value() == 5) ); | ||||
|     PRIVATE_EXPR_TEST( (i = i - i1), (i.value() == 4) ); | ||||
|     PRIVATE_EXPR_TEST( (i = i * i2), (i.value() == 8) ); | ||||
|     PRIVATE_EXPR_TEST( (i = i / i2), (i.value() == 4) ); | ||||
|     PRIVATE_EXPR_TEST( (i = i % ( i - i1 )), (i.value() == 1) ); | ||||
|     PRIVATE_EXPR_TEST( (i = i2 + i2), (i.value() == 4) ); | ||||
|     PRIVATE_EXPR_TEST( (i = i1 | i2 | i), (i.value() == 7) ); | ||||
|     PRIVATE_EXPR_TEST( (i = i & i2), (i.value() == 2) ); | ||||
|     PRIVATE_EXPR_TEST( (i = i + i1), (i.value() == 3) ); | ||||
|     PRIVATE_EXPR_TEST( (i = i ^ i1), (i.value() == 2) ); | ||||
|     PRIVATE_EXPR_TEST( (i = ( i + i1 ) * ( i2 | i1 )), (i.value() == 9) ); | ||||
|  | ||||
|     PRIVATE_EXPR_TEST( (i = i1 << i2), (i.value() == 4) ); | ||||
|     PRIVATE_EXPR_TEST( (i = i2 >> i1), (i.value() == 1) ); | ||||
|      | ||||
|     cout << "Performed tests on MyInt objects.\n"; | ||||
|  | ||||
|     MyLong j1(1); | ||||
|     MyLong j2(2); | ||||
|     MyLong j; | ||||
|  | ||||
|     assert( j1.value() == 1 ); | ||||
|     assert( j2.value() == 2 ); | ||||
|     assert( j.value() == 0 ); | ||||
|     BOOST_TEST( j1.value() == 1 ); | ||||
|     BOOST_TEST( j2.value() == 2 ); | ||||
|     BOOST_TEST( j.value() == 0 ); | ||||
|  | ||||
|     j = j2; | ||||
|     assert( j.value() == 2 ); | ||||
|      | ||||
|     assert( j2 == j ); | ||||
|     assert( 2 == j ); | ||||
|     assert( j2 == 2 );     | ||||
|     assert( j == j2 ); | ||||
|     assert( j1 != j2 ); | ||||
|     assert( j1 != 2 ); | ||||
|     assert( 1 != j2 ); | ||||
|     assert( j1 <  j2 ); | ||||
|     assert( 1 <  j2 ); | ||||
|     assert( j1 <  2 ); | ||||
|     assert( j1 <= j2 ); | ||||
|     assert( 1 <= j2 ); | ||||
|     assert( j1 <= j ); | ||||
|     assert( j <= j2 ); | ||||
|     assert( 2 <= j2 ); | ||||
|     assert( j <= 2 ); | ||||
|     assert( j2 >  j1 ); | ||||
|     assert( 2 >  j1 ); | ||||
|     assert( j2 >  1 ); | ||||
|     assert( j2 >= j1 ); | ||||
|     assert( 2 >= j1 ); | ||||
|     assert( j2 >= 1 ); | ||||
|     assert( j2 >= j ); | ||||
|     assert( 2 >= j ); | ||||
|     assert( j2 >= 2 ); | ||||
|     cout << "Created MyLong objects.\n"; | ||||
|  | ||||
|     assert( (j1 + 2) == 3 ); | ||||
|     assert( (1 + j2) == 3 ); | ||||
|     j = j1 + j2; assert( j.value() == 3 ); | ||||
|     PRIVATE_EXPR_TEST( (j = j2), (j.value() == 2) ); | ||||
|      | ||||
|     assert( (j + 2) == 5 ); | ||||
|     assert( (3 + j2) == 5 ); | ||||
|     j = j + j2; assert( j.value() == 5 ); | ||||
|     BOOST_TEST( j2 == j ); | ||||
|     BOOST_TEST( 2 == j ); | ||||
|     BOOST_TEST( j2 == 2 );     | ||||
|     BOOST_TEST( j == j2 ); | ||||
|     BOOST_TEST( j1 != j2 ); | ||||
|     BOOST_TEST( j1 != 2 ); | ||||
|     BOOST_TEST( 1 != j2 ); | ||||
|     BOOST_TEST( j1 <  j2 ); | ||||
|     BOOST_TEST( 1 <  j2 ); | ||||
|     BOOST_TEST( j1 <  2 ); | ||||
|     BOOST_TEST( j1 <= j2 ); | ||||
|     BOOST_TEST( 1 <= j2 ); | ||||
|     BOOST_TEST( j1 <= j ); | ||||
|     BOOST_TEST( j <= j2 ); | ||||
|     BOOST_TEST( 2 <= j2 ); | ||||
|     BOOST_TEST( j <= 2 ); | ||||
|     BOOST_TEST( j2 >  j1 ); | ||||
|     BOOST_TEST( 2 >  j1 ); | ||||
|     BOOST_TEST( j2 >  1 ); | ||||
|     BOOST_TEST( j2 >= j1 ); | ||||
|     BOOST_TEST( 2 >= j1 ); | ||||
|     BOOST_TEST( j2 >= 1 ); | ||||
|     BOOST_TEST( j2 >= j ); | ||||
|     BOOST_TEST( 2 >= j ); | ||||
|     BOOST_TEST( j2 >= 2 ); | ||||
|  | ||||
|     BOOST_TEST( (j1 + 2) == 3 ); | ||||
|     BOOST_TEST( (1 + j2) == 3 ); | ||||
|     PRIVATE_EXPR_TEST( (j = j1 + j2), (j.value() == 3) ); | ||||
|      | ||||
|     assert( (j - 1) == 4 ); | ||||
|     j = j - j1; assert( j.value() == 4 ); | ||||
|     BOOST_TEST( (j + 2) == 5 ); | ||||
|     BOOST_TEST( (3 + j2) == 5 ); | ||||
|     PRIVATE_EXPR_TEST( (j = j + j2), (j.value() == 5) ); | ||||
|      | ||||
|     assert( (j * 2) == 8 ); | ||||
|     assert( (4 * j2) == 8 ); | ||||
|     j = j * j2; assert( j.value() == 8 ); | ||||
|     BOOST_TEST( (j - 1) == 4 ); | ||||
|     PRIVATE_EXPR_TEST( (j = j - j1), (j.value() == 4) ); | ||||
|      | ||||
|     assert( (j / 2) == 4 ); | ||||
|     j = j / j2; assert( j.value() == 4 ); | ||||
|     BOOST_TEST( (j * 2) == 8 ); | ||||
|     BOOST_TEST( (4 * j2) == 8 ); | ||||
|     PRIVATE_EXPR_TEST( (j = j * j2), (j.value() == 8) ); | ||||
|      | ||||
|     assert( (j % 3) == 1 ); | ||||
|     j = j % (j - j1); assert( j.value() == 1 ); | ||||
|     BOOST_TEST( (j / 2) == 4 ); | ||||
|     PRIVATE_EXPR_TEST( (j = j / j2), (j.value() == 4) ); | ||||
|      | ||||
|     j = j2 + j2; assert( j.value() == 4 ); | ||||
|     BOOST_TEST( (j % 3) == 1 ); | ||||
|     PRIVATE_EXPR_TEST( (j = j % ( j - j1 )), (j.value() == 1) ); | ||||
|      | ||||
|     assert( (1 | j2 | j) == 7 ); | ||||
|     assert( (j1 | 2 | j) == 7 ); | ||||
|     assert( (j1 | j2 | 4) == 7 ); | ||||
|     j = j1 | j2 | j; assert( j.value() == 7 ); | ||||
|     PRIVATE_EXPR_TEST( (j = j2 + j2), (j.value() == 4) ); | ||||
|      | ||||
|     assert( (7 & j2) == 2 ); | ||||
|     assert( (j & 2) == 2 ); | ||||
|     j = j & j2; assert( j.value() == 2 ); | ||||
|     BOOST_TEST( (1 | j2 | j) == 7 ); | ||||
|     BOOST_TEST( (j1 | 2 | j) == 7 ); | ||||
|     BOOST_TEST( (j1 | j2 | 4) == 7 ); | ||||
|     PRIVATE_EXPR_TEST( (j = j1 | j2 | j), (j.value() == 7) ); | ||||
|      | ||||
|     j = j | j1; assert( j.value() == 3 ); | ||||
|     BOOST_TEST( (7 & j2) == 2 ); | ||||
|     BOOST_TEST( (j & 2) == 2 ); | ||||
|     PRIVATE_EXPR_TEST( (j = j & j2), (j.value() == 2) ); | ||||
|      | ||||
|     assert( (3 ^ j1) == 2 ); | ||||
|     assert( (j ^ 1) == 2 ); | ||||
|     j = j ^ j1; assert( j.value() == 2 ); | ||||
|     PRIVATE_EXPR_TEST( (j = j | j1), (j.value() == 3) ); | ||||
|      | ||||
|     j = (j+j1)*(j2|j1); assert( j.value() == 9 ); | ||||
|     BOOST_TEST( (3 ^ j1) == 2 ); | ||||
|     BOOST_TEST( (j ^ 1) == 2 ); | ||||
|     PRIVATE_EXPR_TEST( (j = j ^ j1), (j.value() == 2) ); | ||||
|      | ||||
|     std::cout << "0 errors detected\n"; | ||||
|     return 0; | ||||
|     PRIVATE_EXPR_TEST( (j = ( j + j1 ) * ( j2 | j1 )), (j.value() == 9) ); | ||||
|  | ||||
|     BOOST_TEST( (j1 << 2) == 4 ); | ||||
|     BOOST_TEST( (j2 << 1) == 4 ); | ||||
|     PRIVATE_EXPR_TEST( (j = j1 << j2), (j.value() == 4) ); | ||||
|  | ||||
|     BOOST_TEST( (j >> 2) == 1 ); | ||||
|     BOOST_TEST( (j2 >> 1) == 1 ); | ||||
|     PRIVATE_EXPR_TEST( (j = j2 >> j1), (j.value() == 1) ); | ||||
|      | ||||
|     cout << "Performed tests on MyLong objects.\n"; | ||||
|  | ||||
|     MyChar k1(1); | ||||
|     MyChar k2(2); | ||||
|     MyChar k; | ||||
|  | ||||
|     BOOST_TEST( k1.value() == 1 ); | ||||
|     BOOST_TEST( k2.value() == 2 ); | ||||
|     BOOST_TEST( k.value() == 0 ); | ||||
|  | ||||
|     cout << "Created MyChar objects.\n"; | ||||
|  | ||||
|     PRIVATE_EXPR_TEST( (k = k2), (k.value() == 2) ); | ||||
|  | ||||
|     BOOST_TEST( k2 == k ); | ||||
|     BOOST_TEST( k1 != k2 ); | ||||
|     BOOST_TEST( k1 <  k2 ); | ||||
|     BOOST_TEST( k1 <= k2 ); | ||||
|     BOOST_TEST( k <= k2 ); | ||||
|     BOOST_TEST( k2 >  k1 ); | ||||
|     BOOST_TEST( k2 >= k1 ); | ||||
|     BOOST_TEST( k2 >= k ); | ||||
|      | ||||
|     cout << "Performed tests on MyChar objects.\n"; | ||||
|  | ||||
|     MyShort l1(1); | ||||
|     MyShort l2(2); | ||||
|     MyShort l; | ||||
|  | ||||
|     BOOST_TEST( l1.value() == 1 ); | ||||
|     BOOST_TEST( l2.value() == 2 ); | ||||
|     BOOST_TEST( l.value() == 0 ); | ||||
|  | ||||
|     cout << "Created MyShort objects.\n"; | ||||
|  | ||||
|     PRIVATE_EXPR_TEST( (l = l2), (l.value() == 2) ); | ||||
|      | ||||
|     BOOST_TEST( l2 == l ); | ||||
|     BOOST_TEST( 2 == l ); | ||||
|     BOOST_TEST( l2 == 2 );     | ||||
|     BOOST_TEST( l == l2 ); | ||||
|     BOOST_TEST( l1 != l2 ); | ||||
|     BOOST_TEST( l1 != 2 ); | ||||
|     BOOST_TEST( 1 != l2 ); | ||||
|     BOOST_TEST( l1 <  l2 ); | ||||
|     BOOST_TEST( 1 <  l2 ); | ||||
|     BOOST_TEST( l1 <  2 ); | ||||
|     BOOST_TEST( l1 <= l2 ); | ||||
|     BOOST_TEST( 1 <= l2 ); | ||||
|     BOOST_TEST( l1 <= l ); | ||||
|     BOOST_TEST( l <= l2 ); | ||||
|     BOOST_TEST( 2 <= l2 ); | ||||
|     BOOST_TEST( l <= 2 ); | ||||
|     BOOST_TEST( l2 >  l1 ); | ||||
|     BOOST_TEST( 2 >  l1 ); | ||||
|     BOOST_TEST( l2 >  1 ); | ||||
|     BOOST_TEST( l2 >= l1 ); | ||||
|     BOOST_TEST( 2 >= l1 ); | ||||
|     BOOST_TEST( l2 >= 1 ); | ||||
|     BOOST_TEST( l2 >= l ); | ||||
|     BOOST_TEST( 2 >= l ); | ||||
|     BOOST_TEST( l2 >= 2 ); | ||||
|      | ||||
|     cout << "Performed tests on MyShort objects.\n"; | ||||
|      | ||||
|     return boost::exit_success; | ||||
| } | ||||
|   | ||||
| @@ -371,7 +371,7 @@ Betty | ||||
| </pre> | ||||
|  | ||||
| <hr> | ||||
| <p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->28 Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14390" --></p> | ||||
| <p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->08 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14892" --></p> | ||||
| <p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use, | ||||
| modify, sell and distribute this document is granted provided this copyright | ||||
| notice appears in all copies. This document is provided "as is" | ||||
|   | ||||
| @@ -312,7 +312,7 @@ simply use <tt>reverse_iterator_generator</tt> twice!<br><br> | ||||
|  | ||||
|      | ||||
|     <p>Revised  | ||||
|     <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->28 Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14390" --> | ||||
|     <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->08 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14892" --> | ||||
|  | ||||
|  | ||||
|     <p>© Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell | ||||
|   | ||||
							
								
								
									
										2
									
								
								tie.html
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								tie.html
									
									
									
									
									
								
							| @@ -64,7 +64,7 @@ pair of iterators is assigned to the iterator variables <TT>i</TT> and | ||||
|  | ||||
| <P> | ||||
| Here is another example that uses <TT>tie()</TT> for handling operations with <a | ||||
| href="http://www.sgi.com/Technology/STL/set.html"><TT>std::set</TT></a>. | ||||
| href="http://www.sgi.com/tech/stl/set.html"><TT>std::set</TT></a>. | ||||
|  | ||||
| <P> | ||||
| <PRE> | ||||
|   | ||||
| @@ -71,8 +71,11 @@ public: | ||||
|  | ||||
| <p> | ||||
| The following is an example of how to use the | ||||
| <tt>transform_iterator_generator</tt> class to iterate through a range of | ||||
| numbers, multiplying each of them by 2 when they are dereferenced. | ||||
| <tt>transform_iterator_generator</tt> class to iterate through a range | ||||
| of numbers, multiplying each of them by 2 when they are dereferenced. | ||||
| The <tt>boost::binder1st</tt> class is used instead of the standard | ||||
| one because tranform iterator requires the function object to be | ||||
| Default Constructible. | ||||
|  | ||||
| <p> | ||||
| <PRE> | ||||
| @@ -80,16 +83,18 @@ numbers, multiplying each of them by 2 when they are dereferenced. | ||||
| #include <iostream> | ||||
| #include <boost/iterator_adaptors.hpp> | ||||
|  | ||||
| // definition of class boost::binder1st and function boost::bind1st() ... | ||||
|  | ||||
| int | ||||
| main(int, char*[]) | ||||
| { | ||||
|   int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; | ||||
|  | ||||
|   typedef std::binder1st< std::multiplies<int> > Function; | ||||
|   typedef boost::binder1st< std::multiplies<int> > Function; | ||||
|   typedef boost::transform_iterator_generator<Function, int*>::type doubling_iterator; | ||||
|  | ||||
|   doubling_iterator i(x, std::bind1st(std::multiplies<int>(), 2)), | ||||
|     i_end(x + sizeof(x)/sizeof(int), std::bind1st(std::multiplies<int>(), 2)); | ||||
|   doubling_iterator i(x, boost::bind1st(std::multiplies<int>(), 2)), | ||||
|     i_end(x + sizeof(x)/sizeof(int), boost::bind1st(std::multiplies<int>(), 2)); | ||||
|  | ||||
|   std::cout << "multiplying the array by 2:" << std::endl; | ||||
|   while (i != i_end) | ||||
| @@ -111,14 +116,17 @@ The output from this part is: | ||||
| </TR> | ||||
|  | ||||
| <TR> | ||||
| <TD><a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html"><tt>AdaptableUnaryFunction</tt></a></TD> | ||||
| <TD><a | ||||
| href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html"><tt>AdaptableUnaryFunction</tt></a></TD> | ||||
| <TD>The function object that transforms each element in the iterator | ||||
| range.  The <tt>argument_type</tt> of the function object must match | ||||
| the value type of the base iterator.  The <tt>result_type</tt> of the | ||||
| function object will be the resulting iterator's | ||||
| <tt>value_type</tt>. If you want the resulting iterator to behave as | ||||
| an iterator, the result of the function should be solely a function of | ||||
| its argument.</TD> | ||||
| its argument. Also, the function object must be <a | ||||
| href="http://www.sgi.com/tech/stl/DefaultConstructible.html"> Default | ||||
| Constructible</a> (which many of the standard function objects are not).</TD> | ||||
| </TR> | ||||
|  | ||||
| <TR> | ||||
| @@ -173,8 +181,8 @@ function to add four to each element of the array. | ||||
| <pre> | ||||
|   std::cout << "adding 4 to each element in the array:" << std::endl; | ||||
|  | ||||
|   std::copy(boost::make_transform_iterator(x, std::bind1st(std::plus<int>(), 4)), | ||||
| 	    boost::make_transform_iterator(x + N, std::bind1st(std::plus<int>(), 4)), | ||||
|   std::copy(boost::make_transform_iterator(x, boost::bind1st(std::plus<int>(), 4)), | ||||
| 	    boost::make_transform_iterator(x + N, boost::bind1st(std::plus<int>(), 4)), | ||||
| 	    std::ostream_iterator<int>(std::cout, " ")); | ||||
|   std::cout << std::endl; | ||||
|  | ||||
| @@ -203,7 +211,7 @@ iterator always returns by-value. | ||||
|  | ||||
|  | ||||
| <hr> | ||||
| <p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->09 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14894" --></p> | ||||
| <p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->29 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14896" --></p> | ||||
| <p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use, | ||||
| modify, sell and distribute this document is granted provided this copyright | ||||
| notice appears in all copies. This document is provided "as is" | ||||
|   | ||||
| @@ -9,6 +9,38 @@ | ||||
| #include <iostream> | ||||
| #include <boost/iterator_adaptors.hpp> | ||||
|  | ||||
| // What a bummer. We can't use std::binder1st with transform iterator | ||||
| // because it does not have a default constructor. Here's a version | ||||
| // that does. | ||||
|  | ||||
| namespace boost { | ||||
|  | ||||
|   template <class Operation>  | ||||
|   class binder1st | ||||
|     : public std::unary_function<typename Operation::second_argument_type, | ||||
| 			         typename Operation::result_type> { | ||||
|   protected: | ||||
|     Operation op; | ||||
|     typename Operation::first_argument_type value; | ||||
|   public: | ||||
|     binder1st() { } // this had to be added! | ||||
|     binder1st(const Operation& x, | ||||
| 	      const typename Operation::first_argument_type& y) | ||||
| 	: op(x), value(y) {} | ||||
|     typename Operation::result_type | ||||
|     operator()(const typename Operation::second_argument_type& x) const { | ||||
|       return op(value, x);  | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   template <class Operation, class T> | ||||
|   inline binder1st<Operation> bind1st(const Operation& op, const T& x) { | ||||
|     typedef typename Operation::first_argument_type arg1_type; | ||||
|     return binder1st<Operation>(op, arg1_type(x)); | ||||
|   } | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| int | ||||
| main(int, char*[]) | ||||
| { | ||||
| @@ -20,11 +52,11 @@ main(int, char*[]) | ||||
|   int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; | ||||
|   const int N = sizeof(x)/sizeof(int); | ||||
|  | ||||
|   typedef std::binder1st< std::multiplies<int> > Function; | ||||
|   typedef boost::binder1st< std::multiplies<int> > Function; | ||||
|   typedef boost::transform_iterator_generator<Function, int*>::type doubling_iterator; | ||||
|  | ||||
|   doubling_iterator i(x, std::bind1st(std::multiplies<int>(), 2)), | ||||
|     i_end(x + N, std::bind1st(std::multiplies<int>(), 2)); | ||||
|   doubling_iterator i(x, boost::bind1st(std::multiplies<int>(), 2)), | ||||
|     i_end(x + N, boost::bind1st(std::multiplies<int>(), 2)); | ||||
|  | ||||
|   std::cout << "multiplying the array by 2:" << std::endl; | ||||
|   while (i != i_end) | ||||
| @@ -33,8 +65,8 @@ main(int, char*[]) | ||||
|  | ||||
|   std::cout << "adding 4 to each element in the array:" << std::endl; | ||||
|  | ||||
|   std::copy(boost::make_transform_iterator(x, std::bind1st(std::plus<int>(), 4)), | ||||
| 	    boost::make_transform_iterator(x + N, std::bind1st(std::plus<int>(), 4)), | ||||
|   std::copy(boost::make_transform_iterator(x, boost::bind1st(std::plus<int>(), 4)), | ||||
| 	    boost::make_transform_iterator(x + N, boost::bind1st(std::plus<int>(), 4)), | ||||
| 	    std::ostream_iterator<int>(std::cout, " ")); | ||||
|   std::cout << std::endl; | ||||
|    | ||||
|   | ||||
							
								
								
									
										44
									
								
								utility.htm
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								utility.htm
									
									
									
									
									
								
							| @@ -16,10 +16,50 @@ | ||||
| <h2>Contents</h2> | ||||
|  | ||||
| <ul> | ||||
|   <li>Function templates <a href="#checked_delete">checked_delete() and | ||||
|     checked_array_delete()</a></li> | ||||
|   <li>Function templates <a href="#functions next">next() and prior()</a></li> | ||||
|   <li>Class <a href="#Class noncopyable">noncopyable</a></li> | ||||
|   <li>Function template <a href="tie.html">tie()</a> and supporting class tied.</li> | ||||
| </ul> | ||||
| <h2> Function templates <a name="checked_delete">checked_delete</a>() and | ||||
| checked_array_delete()</h2> | ||||
|  | ||||
| <p>Deletion of a pointer to an incomplete type is an unsafe programming practice | ||||
| because there is no way for the compiler to verify that the destructor is indeed | ||||
| trivial.  The checked_delete() and checked_array_delete() function | ||||
| templates simply <b>delete</b> or <b>delete[]</b> their argument, but also | ||||
| require that their argument be a complete type.  They issue an appropriate | ||||
| compiler error diagnostic if that requirement is not met.  A typical | ||||
| implementation is shown; other implementations may vary:</p> | ||||
|  | ||||
| <pre>    template< typename T > | ||||
|     inline void checked_delete(T const volatile * x) | ||||
|     { | ||||
|         BOOST_STATIC_ASSERT( sizeof(T) ); // assert type complete at point | ||||
|                                           // of instantiation | ||||
|         delete x; | ||||
|     } | ||||
|  | ||||
|     template< typename T > | ||||
|     inline void checked_array_delete(T const volatile * x) | ||||
|     { | ||||
|         BOOST_STATIC_ASSERT( sizeof(T) ); // assert type complete at point | ||||
|                                           // of instantiation | ||||
|         delete [] x; | ||||
|     }</pre> | ||||
|  | ||||
| <p>Contributed by Beman Dawes, based on a suggestion from Dave Abrahams, | ||||
| generalizing an idea from Vladimir Prus, with comments from Rainer Deyke, John | ||||
| Maddock, and others.</p> | ||||
|  | ||||
| <h3>Background</h3> | ||||
|  | ||||
| <p>The C++ Standard specifies that delete on a pointer to an incomplete types is | ||||
| undefined behavior if the type has a non-trivial destructor in  [expr.delete] | ||||
| 5.3.5 paragraph.  No diagnostic is required.  Some but not all | ||||
| compilers issue warnings if the type is incomplete at point of deletion.</p> | ||||
|  | ||||
| <h2> <a name="functions next">Function</a> templates next() and prior()</h2> | ||||
|  | ||||
| <p>Certain data types, such as the C++ Standard Library's forward and | ||||
| @@ -91,9 +131,11 @@ emphasize that it is to be used only as a base class.  Dave Abrahams notes | ||||
| concern about the effect on compiler optimization of adding (even trivial inline) | ||||
| destructor declarations. He says "Probably this concern is misplaced, because | ||||
| noncopyable will be used mostly for classes which own resources and thus have non-trivial destruction semantics."</p> | ||||
| <h2>Function template tie()</h2> | ||||
| <p>See <a href="tie.html">separate documentation</a>.</p> | ||||
| <hr> | ||||
| <p>Revised  <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan | ||||
| -->28 February, 2001<!--webbot bot="Timestamp" endspan i-checksum="40412" | ||||
| -->22 May, 2001<!--webbot bot="Timestamp" endspan i-checksum="13960" | ||||
| --> | ||||
| </p> | ||||
| <p><EFBFBD> Copyright boost.org 1999. Permission to copy, use, modify, sell and | ||||
|   | ||||
		Reference in New Issue
	
	Block a user