summaryrefslogtreecommitdiff
path: root/libs/optional/test/optional_test_swap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/optional/test/optional_test_swap.cpp')
-rw-r--r--libs/optional/test/optional_test_swap.cpp360
1 files changed, 360 insertions, 0 deletions
diff --git a/libs/optional/test/optional_test_swap.cpp b/libs/optional/test/optional_test_swap.cpp
new file mode 100644
index 000000000..b6802b18a
--- /dev/null
+++ b/libs/optional/test/optional_test_swap.cpp
@@ -0,0 +1,360 @@
+// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
+// Copyright (C) 2015 Andrzej Krzemienski.
+//
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/lib/optional for documentation.
+//
+// You are welcome to contact the author at:
+// fernando_cacciola@hotmail.com
+//
+// Revisions:
+// 12 May 2008 (added more swap tests)
+//
+
+#include "boost/optional/optional.hpp"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#include "boost/core/lightweight_test.hpp"
+
+
+using boost::optional;
+using boost::none;
+
+#define ARG(T) (static_cast< T const* >(0))
+
+namespace optional_swap_test
+{
+ class default_ctor_exception : public std::exception {} ;
+ class copy_ctor_exception : public std::exception {} ;
+ class assignment_exception : public std::exception {} ;
+
+ //
+ // Base class for swap test classes. Its assignment should not be called, when swapping
+ // optional<T> objects. (The default std::swap would do so.)
+ //
+ class base_class_with_forbidden_assignment
+ {
+ public:
+ base_class_with_forbidden_assignment & operator=(const base_class_with_forbidden_assignment &)
+ {
+ BOOST_TEST(!"The assignment should not be used while swapping!");
+ throw assignment_exception();
+ }
+
+ virtual ~base_class_with_forbidden_assignment() {}
+ };
+
+ //
+ // Class without default constructor
+ //
+ class class_without_default_ctor : public base_class_with_forbidden_assignment
+ {
+ public:
+ char data;
+ explicit class_without_default_ctor(char arg) : data(arg) {}
+ };
+
+ //
+ // Class whose default constructor should not be used by optional::swap!
+ //
+ class class_whose_default_ctor_should_not_be_used : public base_class_with_forbidden_assignment
+ {
+ public:
+ char data;
+ explicit class_whose_default_ctor_should_not_be_used(char arg) : data(arg) {}
+
+ class_whose_default_ctor_should_not_be_used()
+ {
+ BOOST_TEST(!"This default constructor should not be used while swapping!");
+ throw default_ctor_exception();
+ }
+ };
+
+ //
+ // Class whose default constructor should be used by optional::swap.
+ // Its copy constructor should be avoided!
+ //
+ class class_whose_default_ctor_should_be_used : public base_class_with_forbidden_assignment
+ {
+ public:
+ char data;
+ explicit class_whose_default_ctor_should_be_used(char arg) : data(arg) { }
+
+ class_whose_default_ctor_should_be_used() : data('\0') { }
+
+ class_whose_default_ctor_should_be_used(const class_whose_default_ctor_should_be_used &)
+ {
+ BOOST_TEST(!"This copy constructor should not be used while swapping!");
+ throw copy_ctor_exception();
+ }
+ };
+
+ //
+ // 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_TEST(!"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_TEST(!"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_TEST(!"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);
+ }
+
+ void swap(class_whose_default_ctor_should_be_used & lhs, class_whose_default_ctor_should_be_used & rhs)
+ {
+ std::swap(lhs.data, rhs.data);
+ }
+
+ void swap(class_without_default_ctor & lhs, class_without_default_ctor & rhs)
+ {
+ std::swap(lhs.data, rhs.data);
+ }
+
+ void swap(class_whose_explicit_ctor_should_be_used & lhs, class_whose_explicit_ctor_should_be_used & rhs)
+ {
+ std::swap(lhs.data, rhs.data);
+ }
+
+ 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);
+ }
+
+ //
+ // 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.
+ //
+ 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);
+
+ 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.
+
+
+namespace boost {
+
+//
+// Compile time tweaking on whether or not swap should use the default constructor:
+//
+
+template <> struct optional_swap_should_use_default_constructor<
+ optional_swap_test::class_whose_default_ctor_should_be_used> : mpl::true_ {} ;
+
+template <> struct optional_swap_should_use_default_constructor<
+ optional_swap_test::class_whose_default_ctor_should_not_be_used> : mpl::false_ {} ;
+
+template <class T> struct optional_swap_should_use_default_constructor<
+ optional_swap_test::template_whose_default_ctor_should_be_used<T> > : mpl::true_ {} ;
+
+
+//
+// Specialization of boost::swap:
+//
+template <>
+void swap(optional<optional_swap_test::class_whose_explicit_ctor_should_be_used> & x, optional<optional_swap_test::class_whose_explicit_ctor_should_be_used> & y)
+{
+ optional_swap_test::swap(x, y);
+}
+
+} // namespace boost
+
+
+namespace std {
+
+//
+// Specializations of std::swap:
+//
+
+template <>
+void 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 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 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 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);
+}
+
+} // namespace std
+
+
+//
+// Tests whether the swap function works properly for optional<T>.
+// Assumes that T has one data member, of type char.
+// Returns true iff the test is passed.
+//
+template <class T>
+void test_swap_function( T const* )
+{
+ try
+ {
+ optional<T> obj1;
+ optional<T> obj2('a');
+
+ // Self-swap should not have any effect.
+ swap(obj1, obj1);
+ swap(obj2, obj2);
+ BOOST_TEST(!obj1);
+ BOOST_TEST(!!obj2 && obj2->data == 'a');
+
+ // Call non-member swap.
+ swap(obj1, obj2);
+
+ // Test if obj1 and obj2 are really swapped.
+ BOOST_TEST(!!obj1 && obj1->data == 'a');
+ BOOST_TEST(!obj2);
+
+ // Call non-member swap one more time.
+ swap(obj1, obj2);
+
+ // Test if obj1 and obj2 are swapped back.
+ BOOST_TEST(!obj1);
+ BOOST_TEST(!!obj2 && obj2->data == 'a');
+ }
+ catch(const std::exception &)
+ {
+ // The swap function should not throw, for our test cases.
+ BOOST_TEST(!"throw in swap");
+ }
+}
+
+//
+// Tests whether the optional<T>::swap member function works properly.
+// Assumes that T has one data member, of type char.
+// Returns true iff the test is passed.
+//
+template <class T>
+void test_swap_member_function( T const* )
+{
+ try
+ {
+ optional<T> obj1;
+ optional<T> obj2('a');
+
+ // Self-swap should not have any effect.
+ obj1.swap(obj1);
+ obj2.swap(obj2);
+ BOOST_TEST(!obj1);
+ BOOST_TEST(!!obj2 && obj2->data == 'a');
+
+ // Call member swap.
+ obj1.swap(obj2);
+
+ // Test if obj1 and obj2 are really swapped.
+ BOOST_TEST(!!obj1 && obj1->data == 'a');
+ BOOST_TEST(!obj2);
+
+ // Call member swap one more time.
+ obj1.swap(obj2);
+
+ // Test if obj1 and obj2 are swapped back.
+ BOOST_TEST(!obj1);
+ BOOST_TEST(!!obj2 && obj2->data == 'a');
+ }
+ catch(const std::exception &)
+ {
+ BOOST_TEST(!"throw in swap");
+ }
+}
+
+
+//
+// Tests compile time tweaking of swap, by means of
+// optional_swap_should_use_default_constructor.
+//
+void test_swap_tweaking()
+{
+ ( test_swap_function( ARG(optional_swap_test::class_without_default_ctor) ) );
+ ( test_swap_function( ARG(optional_swap_test::class_whose_default_ctor_should_be_used) ) );
+ ( test_swap_function( ARG(optional_swap_test::class_whose_default_ctor_should_not_be_used) ) );
+ ( test_swap_function( ARG(optional_swap_test::class_whose_explicit_ctor_should_be_used) ) );
+ ( test_swap_function( ARG(optional_swap_test::template_whose_default_ctor_should_be_used<char>) ) );
+ ( test_swap_member_function( ARG(optional_swap_test::class_without_default_ctor) ) );
+ ( test_swap_member_function( ARG(optional_swap_test::class_whose_default_ctor_should_be_used) ) );
+ ( test_swap_member_function( ARG(optional_swap_test::class_whose_default_ctor_should_not_be_used) ) );
+ ( test_swap_member_function( ARG(optional_swap_test::class_whose_explicit_ctor_should_be_used) ) );
+ ( test_swap_member_function( ARG(optional_swap_test::template_whose_default_ctor_should_be_used<char>) ) );
+}
+
+int main()
+{
+ test_swap_tweaking();
+ return boost::report_errors();
+}