Boost logo

Boost-Commit :

From: nielsdekker_at_[hidden]
Date: 2008-05-10 10:53:51


Author: niels_dekker
Date: 2008-05-10 10:53:51 EDT (Sat, 10 May 2008)
New Revision: 45265
URL: http://svn.boost.org/trac/boost/changeset/45265

Log:
Added more optional::swap tests, especially on self swap, on specializing boost::swap for optional<T>, and on swapping optional<T> when T is a template class.
Text files modified:
   trunk/libs/optional/test/optional_test.cpp | 165 ++++++++++++++++++++++++++++++++++++---
   1 files changed, 151 insertions(+), 14 deletions(-)

Modified: trunk/libs/optional/test/optional_test.cpp
==============================================================================
--- trunk/libs/optional/test/optional_test.cpp (original)
+++ trunk/libs/optional/test/optional_test.cpp 2008-05-10 10:53:51 EDT (Sat, 10 May 2008)
@@ -10,7 +10,7 @@
 // fernando_cacciola_at_[hidden]
 //
 // Revisions:
-// 25 Apr 2008 (added more swap tests)
+// 10 May 2008 (added more swap tests)
 //
 #include<iostream>
 #include<stdexcept>
@@ -1000,6 +1000,49 @@
     }
   };
 
+ //
+ // Class template whose default constructor should be used by optional::swap.
+ // Its copy constructor should be avoided!
+ //
+ template <class T>
+ class template_whose_default_ctor_should_be_used : public base_class_with_forbidden_assignment
+ {
+ public:
+ T data;
+ explicit template_whose_default_ctor_should_be_used(T arg) : data(arg) { }
+
+ template_whose_default_ctor_should_be_used() : data('\0') { }
+
+ template_whose_default_ctor_should_be_used(const template_whose_default_ctor_should_be_used &)
+ {
+ BOOST_CHECK(!"This copy constructor should not be used while swapping!");
+ throw copy_ctor_exception();
+ }
+ };
+
+ //
+ // Class whose explicit constructor should be used by optional::swap.
+ // Its other constructors should be avoided!
+ //
+ class class_whose_explicit_ctor_should_be_used : public base_class_with_forbidden_assignment
+ {
+ public:
+ char data;
+ explicit class_whose_explicit_ctor_should_be_used(char arg) : data(arg) { }
+
+ class_whose_explicit_ctor_should_be_used()
+ {
+ BOOST_CHECK(!"This default constructor should not be used while swapping!");
+ throw default_ctor_exception();
+ }
+
+ class_whose_explicit_ctor_should_be_used(const class_whose_explicit_ctor_should_be_used &)
+ {
+ BOOST_CHECK(!"This copy constructor should not be used while swapping!");
+ throw copy_ctor_exception();
+ }
+ };
+
   void swap(class_whose_default_ctor_should_not_be_used & lhs, class_whose_default_ctor_should_not_be_used & rhs)
   {
     std::swap(lhs.data, rhs.data);
@@ -1015,18 +1058,90 @@
     std::swap(lhs.data, rhs.data);
   }
 
-} // End of namespace optional_swap_test.
+ void swap(class_whose_explicit_ctor_should_be_used & lhs, class_whose_explicit_ctor_should_be_used & rhs)
+ {
+ std::swap(lhs.data, rhs.data);
+ }
 
-namespace boost {
+ template <class T>
+ void swap(template_whose_default_ctor_should_be_used<T> & lhs, template_whose_default_ctor_should_be_used<T> & rhs)
+ {
+ std::swap(lhs.data, rhs.data);
+ }
 
   //
- // Compile time tweaking on whether or not swap should use the default constructor:
+ // optional<T>::swap should be customized when neither the copy constructor
+ // nor the default constructor of T are supposed to be used when swapping, e.g.,
+ // for the following type T = class_whose_explicit_ctor_should_be_used.
   //
- template <> struct optional_swap_should_use_default_constructor<
- ::optional_swap_test::class_whose_default_ctor_should_be_used> : mpl::true_ {} ;
+ void swap(boost::optional<class_whose_explicit_ctor_should_be_used> & x, boost::optional<class_whose_explicit_ctor_should_be_used> & y)
+ {
+ bool hasX = x;
+ bool hasY = y;
 
- template <> struct optional_swap_should_use_default_constructor<
- ::optional_swap_test::class_whose_default_ctor_should_not_be_used> : mpl::false_ {} ;
+ if ( !hasX && !hasY )
+ return;
+
+ if( !hasX )
+ x = boost::in_place('\0');
+ else if ( !hasY )
+ y = boost::in_place('\0');
+
+ optional_swap_test::swap(*x,*y);
+
+ if( !hasX )
+ y = boost::none ;
+ else if( !hasY )
+ x = boost::none ;
+ }
+
+
+} // End of namespace optional_swap_test.
+
+
+//
+// Compile time tweaking on whether or not swap should use the default constructor:
+//
+template <> struct boost::optional_swap_should_use_default_constructor<
+ optional_swap_test::class_whose_default_ctor_should_be_used> : boost::mpl::true_ {} ;
+
+template <> struct boost::optional_swap_should_use_default_constructor<
+ optional_swap_test::class_whose_default_ctor_should_not_be_used> : boost::mpl::false_ {} ;
+
+template <class T> struct boost::optional_swap_should_use_default_constructor<
+ optional_swap_test::template_whose_default_ctor_should_be_used<T> > : boost::mpl::true_ {} ;
+
+//
+// Swap specializations:
+//
+template <>
+void boost::swap(boost::optional<optional_swap_test::class_whose_explicit_ctor_should_be_used> & x, boost::optional<optional_swap_test::class_whose_explicit_ctor_should_be_used> & y)
+{
+ optional_swap_test::swap(x, y);
+}
+
+template <>
+void std::swap(optional_swap_test::class_whose_default_ctor_should_be_used & x, optional_swap_test::class_whose_default_ctor_should_be_used & y)
+{
+ optional_swap_test::swap(x, y);
+}
+
+template <>
+void std::swap(optional_swap_test::class_whose_default_ctor_should_not_be_used & x, optional_swap_test::class_whose_default_ctor_should_not_be_used & y)
+{
+ optional_swap_test::swap(x, y);
+}
+
+template <>
+void std::swap(optional_swap_test::class_without_default_ctor & x, optional_swap_test::class_without_default_ctor & y)
+{
+ optional_swap_test::swap(x, y);
+}
+
+template <>
+void std::swap(optional_swap_test::class_whose_explicit_ctor_should_be_used & x, optional_swap_test::class_whose_explicit_ctor_should_be_used & y)
+{
+ optional_swap_test::swap(x, y);
 }
 
 
@@ -1044,16 +1159,25 @@
     optional<T> obj1;
     optional<T> obj2('a');
 
- // Test if obj1 and obj2 are properly initialized.
+ // Self-swap should not have any effect.
+ swap(obj1, obj1);
+ swap(obj2, obj2);
     BOOST_CHECK(!obj1);
     BOOST_CHECK(!!obj2 && obj2->data == 'a');
 
- // Call non-member swap
+ // Call non-member swap.
     swap(obj1, obj2);
 
- // Test if obj1 and obj2 are really swapped
+ // Test if obj1 and obj2 are really swapped.
     BOOST_CHECK(!!obj1 && obj1->data == 'a');
     BOOST_CHECK(!obj2);
+
+ // Call non-member swap one more time.
+ swap(obj1, obj2);
+
+ // Test if obj1 and obj2 are swapped back.
+ BOOST_CHECK(!obj1);
+ BOOST_CHECK(!!obj2 && obj2->data == 'a');
   }
   catch(const std::exception &)
   {
@@ -1077,16 +1201,25 @@
     optional<T> obj1;
     optional<T> obj2('a');
 
- // Test if obj1 and obj2 are properly initialized.
+ // Self-swap should not have any effect.
+ obj1.swap(obj1);
+ obj2.swap(obj2);
     BOOST_CHECK(!obj1);
     BOOST_CHECK(!!obj2 && obj2->data == 'a');
 
- // Call member swap
+ // Call member swap.
     obj1.swap(obj2);
 
- // Test if obj1 and obj2 are really swapped
+ // Test if obj1 and obj2 are really swapped.
     BOOST_CHECK(!!obj1 && obj1->data == 'a');
     BOOST_CHECK(!obj2);
+
+ // Call member swap one more time.
+ obj1.swap(obj2);
+
+ // Test if obj1 and obj2 are swapped back.
+ BOOST_CHECK(!obj1);
+ BOOST_CHECK(!!obj2 && obj2->data == 'a');
   }
   catch(const std::exception &)
   {
@@ -1106,9 +1239,13 @@
   BOOST_CHECK( test_swap_function( ARG(optional_swap_test::class_without_default_ctor) ) );
   BOOST_CHECK( test_swap_function( ARG(optional_swap_test::class_whose_default_ctor_should_be_used) ) );
   BOOST_CHECK( test_swap_function( ARG(optional_swap_test::class_whose_default_ctor_should_not_be_used) ) );
+ BOOST_CHECK( test_swap_function( ARG(optional_swap_test::class_whose_explicit_ctor_should_be_used) ) );
+ BOOST_CHECK( test_swap_function( ARG(optional_swap_test::template_whose_default_ctor_should_be_used<char>) ) );
   BOOST_CHECK( test_swap_member_function( ARG(optional_swap_test::class_without_default_ctor) ) );
   BOOST_CHECK( test_swap_member_function( ARG(optional_swap_test::class_whose_default_ctor_should_be_used) ) );
   BOOST_CHECK( test_swap_member_function( ARG(optional_swap_test::class_whose_default_ctor_should_not_be_used) ) );
+ BOOST_CHECK( test_swap_member_function( ARG(optional_swap_test::class_whose_explicit_ctor_should_be_used) ) );
+ BOOST_CHECK( test_swap_member_function( ARG(optional_swap_test::template_whose_default_ctor_should_be_used<char>) ) );
 }
 
 int test_main( int, char* [] )


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk