diff --git a/test/optional_test.cpp b/test/optional_test.cpp index 2b97c45..ced8a47 100644 --- a/test/optional_test.cpp +++ b/test/optional_test.cpp @@ -26,232 +26,17 @@ #include "boost/test/minimal.hpp" -#ifdef ENABLE_TRACE -#define TRACE(msg) std::cout << msg << std::endl ; -#else -#define TRACE(msg) -#endif +#include "optional_test_common.cpp" -namespace boost { - -void assertion_failed (char const * expr, char const * func, char const * file, long ) +void test_implicit_construction ( optional opt, double v, double z ) { - using std::string ; - string msg = string("Boost assertion failure for \"") - + string(expr) - + string("\" at file \"") - + string(file) - + string("\" function \"") - + string(func) - + string("\"") ; - - TRACE(msg); - - throw std::logic_error(msg); + check_value(opt,v,z); } -} - -using boost::optional ; - -template inline void unused_variable ( T const& ) {} - -#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP -using boost::swap ; -using boost::get_pointer ; -#endif - -// MSVC6.0 does not support comparisons of optional against a literal null pointer value (0) -// via the safe_bool operator. -#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1300) ) // 1300 == VC++ 7.1 -#define BOOST_OPTIONAL_NO_NULL_COMPARE -#endif - -#define ARG(T) (static_cast< T const* >(0)) - -// -// Helper class used to verify the lifetime managment of the values held by optional -// -class X +void test_implicit_construction ( optional opt, X const& v, X const& z ) { - public : - - X ( int av ) : v(av) - { - ++ count ; - - TRACE ( "X::X(" << av << "). this=" << this ) ; - } - - X ( X const& rhs ) : v(rhs.v) - { - pending_copy = false ; - - TRACE ( "X::X( X const& rhs). this=" << this << " rhs.v=" << rhs.v ) ; - - if ( throw_on_copy ) - { - TRACE ( "throwing exception in X's copy ctor" ) ; - throw 0 ; - } - - ++ count ; - } - - ~X() - { - pending_dtor = false ; - - -- count ; - - TRACE ( "X::~X(). v=" << v << " this=" << this ); - } - - X& operator= ( X const& rhs ) - { - v = rhs.v ; - - TRACE ( "X::operator =( X const& rhs). this=" << this << " rhs.v=" << rhs.v ) ; - - return *this ; - } - - friend bool operator == ( X const& a, X const& b ) - { return a.v == b.v ; } - - friend bool operator != ( X const& a, X const& b ) - { return a.v != b.v ; } - - friend bool operator < ( X const& a, X const& b ) - { return a.v < b.v ; } - - int V() const { return v ; } - int& V() { return v ; } - - static int count ; - static bool pending_copy ; - static bool pending_dtor ; - static bool throw_on_copy ; - - private : - - int v ; - - private : - - X() ; -} ; - - -int X::count = 0 ; -bool X::pending_copy = false ; -bool X::pending_dtor = false ; -bool X::throw_on_copy = false ; - -inline void set_pending_copy ( X const* x ) { X::pending_copy = true ; } -inline void set_pending_dtor ( X const* x ) { X::pending_dtor = true ; } -inline void set_throw_on_copy ( X const* x ) { X::throw_on_copy = true ; } -inline void reset_throw_on_copy ( X const* x ) { X::throw_on_copy = false ; } -inline void check_is_pending_copy ( X const* x ) { BOOST_CHECK( X::pending_copy ) ; } -inline void check_is_pending_dtor ( X const* x ) { BOOST_CHECK( X::pending_dtor ) ; } -inline void check_is_not_pending_copy( X const* x ) { BOOST_CHECK( !X::pending_copy ) ; } -inline void check_is_not_pending_dtor( X const* x ) { BOOST_CHECK( !X::pending_dtor ) ; } -inline void check_instance_count ( int c, X const* x ) { BOOST_CHECK( X::count == c ) ; } -inline int get_instance_count ( X const* x ) { return X::count ; } - -inline void set_pending_copy (...) {} -inline void set_pending_dtor (...) {} -inline void set_throw_on_copy (...) {} -inline void reset_throw_on_copy (...) {} -inline void check_is_pending_copy (...) {} -inline void check_is_pending_dtor (...) {} -inline void check_is_not_pending_copy(...) {} -inline void check_is_not_pending_dtor(...) {} -inline void check_instance_count (...) {} -inline int get_instance_count (...) { return 0 ; } - - -template -inline void check_uninitialized_const ( optional const& opt ) -{ -#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE - BOOST_CHECK( opt == 0 ) ; -#endif - BOOST_CHECK( !opt ) ; - BOOST_CHECK( !get_pointer(opt) ) ; - BOOST_CHECK( !opt.get() ) ; + check_value(opt,v,z); } -template -inline void check_uninitialized ( optional& opt ) -{ -#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE - BOOST_CHECK( opt == 0 ) ; -#endif - BOOST_CHECK( !opt ) ; - BOOST_CHECK( !get_pointer(opt) ) ; - BOOST_CHECK( !opt.get() ) ; - - check_uninitialized_const(opt); -} - -template -inline void check_initialized_const ( optional const& opt ) -{ - BOOST_CHECK( opt ) ; - -#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE - BOOST_CHECK( opt != 0 ) ; -#endif - - BOOST_CHECK ( !!opt ) ; - BOOST_CHECK ( get_pointer(opt) ) ; - BOOST_CHECK ( opt.get() ) ; -} - -template -inline void check_initialized ( optional& opt ) -{ - BOOST_CHECK( opt ) ; - -#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE - BOOST_CHECK( opt != 0 ) ; -#endif - - BOOST_CHECK ( !!opt ) ; - BOOST_CHECK ( get_pointer(opt) ) ; - BOOST_CHECK ( opt.get() ) ; - - check_initialized_const(opt); -} - -template -inline void check_value_const ( optional const& opt, T const& v, T const& z ) -{ - BOOST_CHECK( *opt == v ) ; - BOOST_CHECK( *opt != z ) ; - BOOST_CHECK( (*(opt.operator->()) == v) ) ; - BOOST_CHECK( *get_pointer(opt) == v ) ; - BOOST_CHECK( *opt.get() == v ) ; -} - -template -inline void check_value ( optional& opt, T const& v, T const& z ) -{ -#if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) // 1200 == VC++ 6.0 - // For some reason, VC6.0 is creating a temporary while evaluating (*opt == v), - // so we need to turn throw on copy off first. - reset_throw_on_copy( ARG(T) ) ; -#endif - - BOOST_CHECK( *opt == v ) ; - BOOST_CHECK( *opt != z ) ; - BOOST_CHECK( (*(opt.operator->()) == v) ) ; - BOOST_CHECK( *get_pointer(opt) == v ) ; - BOOST_CHECK( *opt.get() == v ) ; - - check_value_const(opt,v,z); -} - // // Basic test. @@ -273,6 +58,10 @@ void test_basics( T const* ) optional def ; check_uninitialized(def); + // Implicit construction + // The first parameter is implicitely converted to optional(a); + test_implicit_construction(a,a,z); + // Direct initialization. // 'oa' state is Initialized with 'a' // T::T( T const& x ) is used. @@ -282,7 +71,6 @@ void test_basics( T const* ) check_initialized(oa); check_value(oa,a,z); - T b(2); optional ob ; @@ -290,19 +78,18 @@ void test_basics( T const* ) // Value-Assignment upon Uninitialized optional. // T::T ( T const& x ) is used. set_pending_copy( ARG(T) ) ; - ob.reset(a) ; + ob = a ; check_is_not_pending_copy( ARG(T) ) ; check_initialized(ob); check_value(ob,a,z); // Value-Assignment upon Initialized optional. - // This uses T::operator= ( T const& x ) directly - // on the reference returned by operator*() + // T::T ( T const& x ) is used set_pending_dtor( ARG(T) ) ; set_pending_copy( ARG(T) ) ; - *ob = b ; - check_is_pending_dtor( ARG(T) ) ; - check_is_pending_copy( ARG(T) ) ; + ob = b ; + check_is_not_pending_dtor( ARG(T) ) ; + check_is_not_pending_copy( ARG(T) ) ; check_initialized(ob); check_value(ob,b,z); @@ -371,6 +158,9 @@ void test_direct_value_manip( T const* ) optional const c_opt0(x) ; optional opt0(x); + BOOST_CHECK( c_opt0.get().V() == x.V() ) ; + BOOST_CHECK( opt0.get().V() == x.V() ) ; + BOOST_CHECK( c_opt0->V() == x.V() ) ; BOOST_CHECK( opt0->V() == x.V() ) ; @@ -378,10 +168,8 @@ void test_direct_value_manip( T const* ) BOOST_CHECK( (* opt0).V() == x.V() ) ; T y(4); - *opt0 = y ; - BOOST_CHECK( (*opt0).V() == y.V() ) ; - - BOOST_CHECK( x < (*opt0) ) ; + opt0 = y ; + BOOST_CHECK( get(opt0).V() == y.V() ) ; } // @@ -398,13 +186,24 @@ void test_uninitialized_access( T const* ) try { // This should throw because 'def' is uninitialized - T const& n = *def ; + T const& n = def.get() ; unused_variable(n); passed = true ; } catch (...) {} BOOST_CHECK(!passed); + passed = false ; + try + { + // This should throw because 'def' is uninitialized + T const& n = *def ; + unused_variable(n); + passed = true ; + } + catch (...) {} + BOOST_CHECK(!passed); + passed = false ; try { @@ -706,8 +505,6 @@ void test_no_throwing_swap( T const* ) int count = get_instance_count( ARG(T) ) ; - using boost::swap ; - swap(def0,def1); check_uninitialized(def0); check_uninitialized(def1); @@ -819,17 +616,37 @@ void test_relops( T const* ) BOOST_CHECK ( !(def0 != def0) ) ; BOOST_CHECK ( !(opt0 != opt0) ) ; - // If both are uininitalized they compare equal - BOOST_CHECK ( def0 == def1 ) ; + // Check when both are uininitalized. + BOOST_CHECK ( def0 == def1 ) ; // both uninitialized compare equal + BOOST_CHECK ( !(def0 < def1) ) ; // uninitialized is never less than uninitialized + BOOST_CHECK ( !(def0 > def1) ) ; // uninitialized is never greater than uninitialized BOOST_CHECK ( !(def0 != def1) ) ; + BOOST_CHECK ( def0 <= def1 ) ; + BOOST_CHECK ( def0 >= def1 ) ; - // If only one is initialized they compare unequal - BOOST_CHECK ( def0 != opt0 ) ; - BOOST_CHECK ( !(def1 == opt1) ) ; + // Check when only lhs is uninitialized. + BOOST_CHECK ( def0 != opt0 ) ; // uninitialized is never equal to initialized + BOOST_CHECK ( !(def0 == opt0) ) ; + BOOST_CHECK ( def0 < opt0 ) ; // uninitialized is always less than initialized + BOOST_CHECK ( !(def0 > opt0) ) ; + BOOST_CHECK ( def0 <= opt0 ) ; + BOOST_CHECK ( !(def0 >= opt0) ) ; + // Check when only rhs is uninitialized. + BOOST_CHECK ( opt0 != def0 ) ; // initialized is never equal to uninitialized + BOOST_CHECK ( !(opt0 == def0) ) ; + BOOST_CHECK ( !(opt0 < def0) ) ; // initialized is never less than uninitialized + BOOST_CHECK ( opt0 > def0 ) ; + BOOST_CHECK ( !(opt0 <= def0) ) ; + BOOST_CHECK ( opt0 >= opt0 ) ; + // If both are initialized, values are compared BOOST_CHECK ( opt0 != opt1 ) ; BOOST_CHECK ( opt1 == opt2 ) ; + BOOST_CHECK ( opt0 < opt1 ) ; + BOOST_CHECK ( opt1 > opt0 ) ; + BOOST_CHECK ( opt1 <= opt2 ) ; + BOOST_CHECK ( opt1 >= opt0 ) ; } void test_with_builtin_types() @@ -893,7 +710,7 @@ void test_no_implicit_conversions() } struct A {} ; -void test_conversions() +void test_conversions1() { TRACE( std::endl << BOOST_CURRENT_FUNCTION ); @@ -914,6 +731,20 @@ void test_conversions() #endif } +void test_conversions2() +{ + TRACE( std::endl << BOOST_CURRENT_FUNCTION ); + + char c = 20 ; + optional opt(c); + BOOST_CHECK( get(opt) == static_cast(c)); + + float f = 21.22f ; + optional opt1; + opt1 = f ; + BOOST_CHECK(*get(&opt1) == static_cast(f)); +} + int test_main( int, char* [] ) { try @@ -921,7 +752,8 @@ int test_main( int, char* [] ) test_with_class_type(); test_with_builtin_types(); test_no_implicit_conversions(); - test_conversions(); + test_conversions1(); + test_conversions2(); } catch ( ... ) {