// Copyright (C) 2003, Fernando Luis Cacciola Carballal. // // 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 // #include #include #include #define BOOST_ENABLE_ASSERT_HANDLER #include "boost/optional.hpp" #ifdef __BORLANDC__ #pragma hdrstop #endif #include "boost/none.hpp" #include "boost/test/minimal.hpp" #include "optional_test_common.cpp" template inline void check_ref_uninitialized_const ( optional const& opt ) { #ifndef BOOST_OPTIONAL_NO_NULL_COMPARE BOOST_CHECK( opt == 0 ) ; #endif BOOST_CHECK( !opt ) ; } template inline void check_ref_uninitialized ( optional& opt ) { #ifndef BOOST_OPTIONAL_NO_NULL_COMPARE BOOST_CHECK( opt == 0 ) ; #endif BOOST_CHECK( !opt ) ; check_ref_uninitialized_const(opt); } template inline void check_ref_initialized_const ( optional const& opt ) { BOOST_CHECK( opt ) ; #ifndef BOOST_OPTIONAL_NO_NULL_COMPARE BOOST_CHECK( opt != 0 ) ; #endif BOOST_CHECK ( !!opt ) ; } template inline void check_ref_initialized ( optional& opt ) { BOOST_CHECK( opt ) ; #ifndef BOOST_OPTIONAL_NO_NULL_COMPARE BOOST_CHECK( opt != 0 ) ; #endif BOOST_CHECK ( !!opt ) ; check_ref_initialized_const(opt); } template inline void check_ref_value_const ( optional const& opt, T const& v, T const& z ) { BOOST_CHECK( *opt == v ) ; BOOST_CHECK( *opt != z ) ; BOOST_CHECK( opt.get() == v ) ; BOOST_CHECK( opt.get() != z ) ; } template inline void check_ref_value ( optional& opt, T const& v, T const& z ) { BOOST_CHECK( *opt == v ) ; BOOST_CHECK( *opt != z ) ; BOOST_CHECK( opt.get() == v ) ; BOOST_CHECK( opt.get() != z ) ; check_ref_value_const(opt,v,z); } // // Basic test. // Check ordinary functionality: // Initialization, assignment, comparison and value-accessing. // template void test_basics( T const* ) { TRACE( std::endl << BOOST_CURRENT_FUNCTION ); T z(0); T original_a(1); T a(1); T b(2); T c(10); T& aref = a ; T& bref = b ; // Default construction. // 'def' state is Uninitialized. // T::T() is not called optional def ; check_ref_uninitialized(def); // Direct initialization. // 'oa' state is Initialized and binds to 'a' // T::T( T const& x ) is NOT used becasue the optional holds a reference. set_pending_copy( ARG(T) ) ; optional oa ( aref ) ; check_is_pending_copy( ARG(T) ); check_ref_initialized(oa); check_ref_value(oa,a,z); *oa = b ; // changes the value of 'a' through the reference BOOST_CHECK( a == b ) ; // Copy initialization. // T::T ( T const& x ) is NOT used becasue the optional holds a reference. set_pending_copy( ARG(T) ) ; optional const oa2 ( oa ) ; check_is_pending_copy( ARG(T) ) ; check_ref_initialized_const(oa2); check_ref_value_const(oa2,a,z); *oa2 = original_a ; // restores the value of 'a' through the reference BOOST_CHECK( a == original_a ) ; optional ob ; // Value-Assignment upon Uninitialized optional. // T::T ( T const& x ) is NOT used becasue the optional holds a reference. set_pending_copy( ARG(T) ) ; ob = a ; // Binds ob to a temporary non-const refererence to 'a' check_is_pending_copy( ARG(T) ) ; check_ref_initialized(ob); check_ref_value(ob,a,z); a = c; check_ref_value(ob,a,z); // Value-Assignment upon Initialized optional. // T::operator= ( T const& x ) is used. set_pending_assign( ARG(T) ) ; ob = b ; // Rebinds 'ob' to 'b' (without changing 'a') check_is_pending_assign( ARG(T) ) ; check_ref_initialized(ob); check_ref_value(ob,b,z); BOOST_CHECK(a == c); // From a=c in previous test b = c; check_ref_value(ob,b,z); // Assignment initialization. // T::T ( T const& x ) is NOT used becasue the optional holds a reference. set_pending_copy( ARG(T) ) ; optional const oa3 = b ; check_is_pending_copy( ARG(T) ) ; check_ref_initialized_const(oa3); check_ref_value_const(oa3,b,z); // Assignment // T::operator=( T const& x ) is used. set_pending_assign( ARG(T) ) ; oa = ob ; // Rebinds 'a' to 'b' check_is_pending_assign( ARG(T) ) ; check_ref_initialized(oa); a = original_a ; check_ref_value(oa,b,z); // Uninitializing Assignment upon Initialized Optional // T::~T() is NOT used becasue the optional holds a reference. set_pending_dtor( ARG(T) ) ; set_pending_copy( ARG(T) ) ; oa = def ; check_is_pending_dtor( ARG(T) ) ; check_is_pending_copy( ARG(T) ) ; check_ref_uninitialized(oa); // Uninitializing Assignment upon Uninitialized Optional // (Dtor is not called this time) set_pending_dtor( ARG(T) ) ; set_pending_copy( ARG(T) ) ; oa = def ; check_is_pending_dtor( ARG(T) ) ; check_is_pending_copy( ARG(T) ) ; check_ref_uninitialized(oa); // Deinitialization of Initialized Optional // T::~T() is NOT used becasue the optional holds a reference. set_pending_dtor( ARG(T) ) ; ob.reset(); check_is_pending_dtor( ARG(T) ) ; check_ref_uninitialized(ob); // Deinitialization of Uninitialized Optional // T::~T() is not called this time set_pending_dtor( ARG(T) ) ; ob.reset(); check_is_pending_dtor( ARG(T) ) ; check_ref_uninitialized(ob); } // // This verifies relational operators. // template void test_relops( T const* ) { TRACE( std::endl << BOOST_CURRENT_FUNCTION ); reset_throw_on_copy( ARG(T) ) ; T v0(18); T v1(19); T v2(19); optional def0 ; optional def1 ; optional opt0(v0); optional opt1(v1); optional opt2(v2); // Check identity BOOST_CHECK ( def0 == def0 ) ; BOOST_CHECK ( opt0 == opt0 ) ; BOOST_CHECK ( !(def0 != def0) ) ; BOOST_CHECK ( !(opt0 != opt0) ) ; // 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 ) ; // 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 ) ; } template void test_none( T const* ) { TRACE( std::endl << BOOST_CURRENT_FUNCTION ); using boost::none ; T a(1234); optional def0 ; optional def1(none) ; optional non_def(a) ; BOOST_CHECK ( def0 == none ) ; BOOST_CHECK ( non_def != none ) ; BOOST_CHECK ( !def1 ) ; non_def = none ; BOOST_CHECK ( !non_def ) ; } template void test_arrow( T const* ) { TRACE( std::endl << BOOST_CURRENT_FUNCTION ); T a(1234); optional oa(a) ; optional const coa(a) ; BOOST_CHECK ( coa->V() == 1234 ) ; oa->V() = 4321 ; BOOST_CHECK ( a.V() = 4321 ) ; } void test_with_builtin_types() { TRACE( std::endl << BOOST_CURRENT_FUNCTION ); test_basics( ARG(double) ); test_relops( ARG(double) ) ; test_none ( ARG(double) ) ; } void test_with_class_type() { TRACE( std::endl << BOOST_CURRENT_FUNCTION ); test_basics( ARG(X) ); test_relops( ARG(X) ) ; test_none ( ARG(X) ) ; test_arrow ( ARG(X) ) ; BOOST_CHECK ( X::count == 0 ) ; } int test_main( int, char* [] ) { try { test_with_class_type(); test_with_builtin_types(); } catch ( ... ) { BOOST_ERROR("Unexpected Exception caught!"); } return 0; }