optional/test/optional_test_common.hpp
Andrzej Krzemienski 5182f7f30f Added has_value()
2018-03-24 00:04:15 +01:00

284 lines
7.7 KiB
C++

// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
// Copyright (C) 2014, 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
//
#include <boost/core/ignore_unused.hpp>
#ifdef ENABLE_TRACE
#define TRACE(msg) std::cout << msg << std::endl ;
#else
#define TRACE(msg)
#endif
namespace boost {
void assertion_failed (char const * expr, char const * func, char const * file, long )
{
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);
}
}
using boost::optional ;
#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
using boost::swap ;
using boost::get ;
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
#else
#define BOOST_OPTIONAL_NO_NULL_COMPARE // Andrzej: I also disable 0 comparison everywhere
#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
{
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 )
{
pending_assign = false ;
if ( throw_on_assign )
{
TRACE ( "throwing exception in X's assignment" ) ;
v = -1 ;
throw 0 ;
}
else
{
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 pending_assign ;
static bool throw_on_copy ;
static bool throw_on_assign ;
private :
int v ;
private :
X() ;
} ;
int X::count = 0 ;
bool X::pending_copy = false ;
bool X::pending_dtor = false ;
bool X::pending_assign = false ;
bool X::throw_on_copy = false ;
bool X::throw_on_assign = false ;
inline void set_pending_copy ( X const* ) { X::pending_copy = true ; }
inline void set_pending_dtor ( X const* ) { X::pending_dtor = true ; }
inline void set_pending_assign ( X const* ) { X::pending_assign = true ; }
inline void set_throw_on_copy ( X const* ) { X::throw_on_copy = true ; }
inline void set_throw_on_assign ( X const* ) { X::throw_on_assign = true ; }
inline void reset_throw_on_copy ( X const* ) { X::throw_on_copy = false ; }
inline void reset_throw_on_assign ( X const* ) { X::throw_on_assign = false ; }
inline void check_is_pending_copy ( X const* ) { BOOST_TEST( X::pending_copy ) ; }
inline void check_is_pending_dtor ( X const* ) { BOOST_TEST( X::pending_dtor ) ; }
inline void check_is_pending_assign ( X const* ) { BOOST_TEST( X::pending_assign ) ; }
inline void check_is_not_pending_copy ( X const* ) { BOOST_TEST( !X::pending_copy ) ; }
inline void check_is_not_pending_dtor ( X const* ) { BOOST_TEST( !X::pending_dtor ) ; }
inline void check_is_not_pending_assign( X const* ) { BOOST_TEST( !X::pending_assign ) ; }
inline void check_instance_count ( int c, X const* ) { BOOST_TEST( X::count == c ) ; }
inline int get_instance_count ( X const* ) { return X::count ; }
inline void set_pending_copy (...) {}
inline void set_pending_dtor (...) {}
inline void set_pending_assign (...) {}
inline void set_throw_on_copy (...) {}
inline void set_throw_on_assign (...) {}
inline void reset_throw_on_copy (...) {}
inline void reset_throw_on_assign (...) {}
inline void check_is_pending_copy (...) {}
inline void check_is_pending_dtor (...) {}
inline void check_is_pending_assign (...) {}
inline void check_is_not_pending_copy (...) {}
inline void check_is_not_pending_dtor (...) {}
inline void check_is_not_pending_assign(...) {}
inline void check_instance_count (...) {}
inline int get_instance_count (...) { return 0 ; }
template<class T>
inline void check_uninitialized_const ( optional<T> const& opt )
{
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
BOOST_TEST( opt == 0 ) ;
#endif
BOOST_TEST( !opt ) ;
BOOST_TEST( !get_pointer(opt) ) ;
BOOST_TEST( !opt.get_ptr() ) ;
BOOST_TEST( !opt.has_value() ) ;
BOOST_TEST( !opt.is_initialized() ) ;
BOOST_TEST( opt == boost::none ) ;
}
template<class T>
inline void check_uninitialized ( optional<T>& opt )
{
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
BOOST_TEST( opt == 0 ) ;
#endif
BOOST_TEST( !opt ) ;
BOOST_TEST( !get_pointer(opt) ) ;
BOOST_TEST( !opt.get_ptr() ) ;
BOOST_TEST( !opt.has_value() ) ;
BOOST_TEST( !opt.is_initialized() ) ;
BOOST_TEST( opt == boost::none ) ;
check_uninitialized_const(opt);
}
template<class T>
inline void check_initialized_const ( optional<T> const& opt )
{
BOOST_TEST( opt ) ;
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
BOOST_TEST( opt != 0 ) ;
#endif
BOOST_TEST ( !!opt ) ;
BOOST_TEST ( get_pointer(opt) ) ;
BOOST_TEST ( opt.get_ptr() ) ;
BOOST_TEST ( opt.has_value() ) ;
BOOST_TEST ( opt.is_initialized() ) ;
BOOST_TEST ( opt != boost::none ) ;
}
template<class T>
inline void check_initialized ( optional<T>& opt )
{
BOOST_TEST( opt ) ;
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
BOOST_TEST( opt != 0 ) ;
#endif
BOOST_TEST ( !!opt ) ;
BOOST_TEST ( get_pointer(opt) ) ;
BOOST_TEST ( opt.get_ptr() ) ;
BOOST_TEST ( opt.has_value() ) ;
BOOST_TEST ( opt.is_initialized() ) ;
BOOST_TEST ( opt != boost::none ) ;
check_initialized_const(opt);
}
template<class T>
inline void check_value_const ( optional<T> const& opt, T const& v, T const& z )
{
BOOST_TEST( *opt == v ) ;
BOOST_TEST( *opt != z ) ;
BOOST_TEST( opt.get() == v ) ;
BOOST_TEST( opt.get() != z ) ;
BOOST_TEST( (*(opt.operator->()) == v) ) ;
BOOST_TEST( *get_pointer(opt) == v ) ;
}
template<class T>
inline void check_value ( optional<T>& 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_TEST( *opt == v ) ;
BOOST_TEST( *opt != z ) ;
BOOST_TEST( opt.get() == v ) ;
BOOST_TEST( opt.get() != z ) ;
BOOST_TEST( (*(opt.operator->()) == v) ) ;
BOOST_TEST( *get_pointer(opt) == v ) ;
check_value_const(opt,v,z);
}