mirror of
				https://github.com/boostorg/optional.git
				synced 2025-11-04 09:41:37 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			374 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			374 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// 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<iostream>
 | 
						|
#include<stdexcept>
 | 
						|
#include<string>
 | 
						|
 | 
						|
#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<class T>
 | 
						|
inline void check_ref_uninitialized_const ( optional<T&> const& opt )
 | 
						|
{
 | 
						|
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
 | 
						|
  BOOST_CHECK( opt == 0 ) ;
 | 
						|
#endif
 | 
						|
  BOOST_CHECK( !opt ) ;
 | 
						|
}
 | 
						|
template<class T>
 | 
						|
inline void check_ref_uninitialized ( optional<T&>& opt )
 | 
						|
{
 | 
						|
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
 | 
						|
  BOOST_CHECK( opt == 0 ) ;
 | 
						|
#endif
 | 
						|
  BOOST_CHECK( !opt ) ;
 | 
						|
 | 
						|
  check_ref_uninitialized_const(opt);
 | 
						|
}
 | 
						|
 | 
						|
template<class T>
 | 
						|
inline void check_ref_initialized_const ( optional<T&> const& opt )
 | 
						|
{
 | 
						|
  BOOST_CHECK( opt ) ;
 | 
						|
 | 
						|
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
 | 
						|
  BOOST_CHECK( opt != 0 ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  BOOST_CHECK ( !!opt ) ;
 | 
						|
}
 | 
						|
 | 
						|
template<class T>
 | 
						|
inline void check_ref_initialized ( optional<T&>& opt )
 | 
						|
{
 | 
						|
  BOOST_CHECK( opt ) ;
 | 
						|
 | 
						|
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
 | 
						|
  BOOST_CHECK( opt != 0 ) ;
 | 
						|
#endif
 | 
						|
 | 
						|
  BOOST_CHECK ( !!opt ) ;
 | 
						|
 | 
						|
  check_ref_initialized_const(opt);
 | 
						|
}
 | 
						|
 | 
						|
template<class T>
 | 
						|
inline void check_ref_value_const ( optional<T&> 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<class T>
 | 
						|
inline void check_ref_value ( optional<T&>& 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<class T>
 | 
						|
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<T&> 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<T&> 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<T&>  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<T&> 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<T&> 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<class T>
 | 
						|
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<T&> def0 ;
 | 
						|
  optional<T&> def1 ;
 | 
						|
  optional<T&> opt0(v0);
 | 
						|
  optional<T&> opt1(v1);
 | 
						|
  optional<T&> 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<class T>
 | 
						|
void test_none( T const* )
 | 
						|
{
 | 
						|
  TRACE( std::endl << BOOST_CURRENT_FUNCTION   );
 | 
						|
 | 
						|
  using boost::none ;
 | 
						|
 | 
						|
  T a(1234);
 | 
						|
 | 
						|
  optional<T&> def0 ;
 | 
						|
  optional<T&> def1(none) ;
 | 
						|
  optional<T&> non_def(a) ;
 | 
						|
 | 
						|
  BOOST_CHECK ( def0    == none ) ;
 | 
						|
  BOOST_CHECK ( non_def != none ) ;
 | 
						|
  BOOST_CHECK ( !def1           ) ;
 | 
						|
 | 
						|
  non_def = none ;
 | 
						|
  BOOST_CHECK ( !non_def ) ;
 | 
						|
}
 | 
						|
 | 
						|
template<class T>
 | 
						|
void test_arrow( T const* )
 | 
						|
{
 | 
						|
  TRACE( std::endl << BOOST_CURRENT_FUNCTION   );
 | 
						|
 | 
						|
  T a(1234);
 | 
						|
 | 
						|
  optional<T&>        oa(a) ;
 | 
						|
  optional<T&> 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 ) ;
 | 
						|
}
 | 
						|
 | 
						|
void test_binding()
 | 
						|
{
 | 
						|
  int i = 0 ;
 | 
						|
  optional<int&> ori1 = i ;
 | 
						|
  BOOST_CHECK(  &(*ori1) == &i ) ;
 | 
						|
 | 
						|
  optional<int&> ori2(i) ;
 | 
						|
  BOOST_CHECK(  &(*ori2) == &i ) ;
 | 
						|
 | 
						|
  int const ci = 0 ;
 | 
						|
  optional<int const&> orci1 = ci ;
 | 
						|
  BOOST_CHECK(  &(*orci1) == &ci ) ;
 | 
						|
 | 
						|
  optional<int const&> orci2(ci) ;
 | 
						|
  BOOST_CHECK(  &(*orci2) == &ci ) ;
 | 
						|
}
 | 
						|
 | 
						|
int test_main( int, char* [] )
 | 
						|
{
 | 
						|
  try
 | 
						|
  {
 | 
						|
    test_with_class_type();
 | 
						|
    test_with_builtin_types();
 | 
						|
    test_binding();
 | 
						|
  }
 | 
						|
  catch ( ... )
 | 
						|
  {
 | 
						|
    BOOST_ERROR("Unexpected Exception caught!");
 | 
						|
  }
 | 
						|
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
 |