forked from boostorg/optional
Compare commits
37 Commits
boost-1.43
...
svn-branch
Author | SHA1 | Date | |
---|---|---|---|
7734d69cb9 | |||
e9989b260e | |||
646488e0e2 | |||
64d8062621 | |||
d39627c5b6 | |||
f88c8ae423 | |||
ab01dfff7e | |||
8608ad1497 | |||
c93e5a88c7 | |||
425d141cbf | |||
57c07c7a57 | |||
97e314f03a | |||
bccd75c72f | |||
16f0a0aaaf | |||
a63dbe0f14 | |||
066dd6f345 | |||
4e628ed4a6 | |||
8682f2bbaa | |||
fea89e84f3 | |||
2772bfc08d | |||
361943e033 | |||
20c9fc8ebe | |||
fd38be1636 | |||
9f655c6932 | |||
e7d7b014d2 | |||
2af3ec341b | |||
3ebabcb2d8 | |||
63f6e7f45e | |||
43eac5bb12 | |||
74674531c8 | |||
a4572497be | |||
951b49f992 | |||
1afed544db | |||
66c366d18a | |||
472a68c920 | |||
3e33d4a200 | |||
95c864e119 |
@ -24,7 +24,7 @@ boostbook standalone
|
||||
optional
|
||||
:
|
||||
<xsl:param>boost.root=../../../..
|
||||
<xsl:param>boost.libraries=../../../libraries.htm
|
||||
<xsl:param>html.stylesheet=boostbook.css
|
||||
<xsl:param>toc.max.depth=2
|
||||
<xsl:param>toc.section.depth=2
|
||||
<xsl:param>chunk.section.depth=1
|
||||
|
@ -4,7 +4,7 @@
|
||||
// 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.
|
||||
// See http://www.boost.org/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
namespace boost {
|
||||
|
||||
none_t const none = ((none_t)0) ;
|
||||
none_t const none = (static_cast<none_t>(0)) ;
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
@ -1,35 +1,42 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2003, 2008 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.
|
||||
// See http://www.boost.org/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
// Revisions:
|
||||
// 27 Apr 2008 (improved swap) Fernando Cacciola, Niels Dekker, Thorsten Ottosen
|
||||
//
|
||||
#ifndef BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
|
||||
#define BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
|
||||
|
||||
#include<new>
|
||||
#include<algorithm>
|
||||
#include <new>
|
||||
#include <algorithm>
|
||||
|
||||
#include "boost/config.hpp"
|
||||
#include "boost/assert.hpp"
|
||||
#include "boost/type.hpp"
|
||||
#include "boost/type_traits/alignment_of.hpp"
|
||||
#include "boost/type_traits/type_with_alignment.hpp"
|
||||
#include "boost/type_traits/remove_reference.hpp"
|
||||
#include "boost/type_traits/is_reference.hpp"
|
||||
#include "boost/mpl/if.hpp"
|
||||
#include "boost/mpl/bool.hpp"
|
||||
#include "boost/mpl/not.hpp"
|
||||
#include "boost/detail/reference_content.hpp"
|
||||
#include "boost/none.hpp"
|
||||
#include "boost/utility/compare_pointees.hpp"
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/type.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <boost/type_traits/has_nothrow_constructor.hpp>
|
||||
#include <boost/type_traits/type_with_alignment.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/type_traits/is_reference.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/detail/reference_content.hpp>
|
||||
#include <boost/none.hpp>
|
||||
#include <boost/utility/swap.hpp>
|
||||
#include <boost/utility/addressof.hpp>
|
||||
#include <boost/utility/compare_pointees.hpp>
|
||||
#include <boost/utility/in_place_factory.hpp>
|
||||
|
||||
#include "boost/optional/optional_fwd.hpp"
|
||||
#include <boost/optional/optional_fwd.hpp>
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
|
||||
// VC6.0 has the following bug:
|
||||
@ -76,6 +83,15 @@
|
||||
#define BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) > 302 \
|
||||
&& !defined(__INTEL_COMPILER)
|
||||
// GCC since 3.3 has may_alias attribute that helps to alleviate optimizer issues with
|
||||
// regard to violation of the strict aliasing rules. The optional< T > storage type is marked
|
||||
// with this attribute in order to let the compiler know that it will alias objects of type T
|
||||
// and silence compilation warnings.
|
||||
#define BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS
|
||||
#endif
|
||||
|
||||
// Daniel Wallin discovered that bind/apply.hpp badly interacts with the apply<>
|
||||
// member template of a factory as used in the optional<> implementation.
|
||||
// He proposed this simple fix which is to move the call to apply<> outside
|
||||
@ -83,7 +99,7 @@
|
||||
namespace boost_optional_detail
|
||||
{
|
||||
template <class T, class Factory>
|
||||
void construct(Factory const& factory, void* address)
|
||||
inline void construct(Factory const& factory, void* address)
|
||||
{
|
||||
factory.BOOST_NESTED_TEMPLATE apply<T>(address);
|
||||
}
|
||||
@ -95,6 +111,9 @@ namespace boost {
|
||||
class in_place_factory_base ;
|
||||
class typed_in_place_factory_base ;
|
||||
|
||||
// This forward is needed to refer to namespace scope swap from the member swap
|
||||
template<class T> void swap ( optional<T>& x, optional<T>& y );
|
||||
|
||||
namespace optional_detail {
|
||||
|
||||
// This local class is used instead of that in "aligned_storage.hpp"
|
||||
@ -105,7 +124,12 @@ template <class T>
|
||||
class aligned_storage
|
||||
{
|
||||
// Borland ICEs if unnamed unions are used for this!
|
||||
union dummy_u
|
||||
union
|
||||
// This works around GCC warnings about breaking strict aliasing rules when casting storage address to T*
|
||||
#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
|
||||
__attribute__((may_alias))
|
||||
#endif
|
||||
dummy_u
|
||||
{
|
||||
char data[ sizeof(T) ];
|
||||
BOOST_DEDUCED_TYPENAME type_with_alignment<
|
||||
@ -114,8 +138,13 @@ class aligned_storage
|
||||
|
||||
public:
|
||||
|
||||
void const* address() const { return &dummy_.data[0]; }
|
||||
void * address() { return &dummy_.data[0]; }
|
||||
#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
|
||||
void const* address() const { return &dummy_; }
|
||||
void * address() { return &dummy_; }
|
||||
#else
|
||||
void const* address() const { return dummy_.data; }
|
||||
void * address() { return dummy_.data; }
|
||||
#endif
|
||||
} ;
|
||||
|
||||
template<class T>
|
||||
@ -149,7 +178,7 @@ class optional_base : public optional_tag
|
||||
typedef
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
BOOST_DEDUCED_TYPENAME
|
||||
#endif
|
||||
#endif
|
||||
::boost::detail::make_reference_content<T>::type internal_type ;
|
||||
|
||||
typedef aligned_storage<internal_type> storage_type ;
|
||||
@ -168,8 +197,10 @@ class optional_base : public optional_tag
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME is_reference<T>::type is_reference_predicate ;
|
||||
|
||||
public:
|
||||
typedef BOOST_DEDUCED_TYPENAME mpl::if_<is_reference_predicate,types_when_ref,types_when_not_ref>::type types ;
|
||||
|
||||
protected:
|
||||
typedef bool (this_type::*unspecified_bool_type)() const;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME types::reference_type reference_type ;
|
||||
@ -198,7 +229,7 @@ class optional_base : public optional_tag
|
||||
{
|
||||
construct(val);
|
||||
}
|
||||
|
||||
|
||||
// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialzed optional<T>.
|
||||
// Can throw if T::T(T const&) does
|
||||
optional_base ( bool cond, argument_type val )
|
||||
@ -419,8 +450,22 @@ class optional_base : public optional_tag
|
||||
private :
|
||||
|
||||
// internal_type can be either T or reference_content<T>
|
||||
#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
|
||||
// This workaround is supposed to silence GCC warnings about broken strict aliasing rules
|
||||
internal_type const* get_object() const
|
||||
{
|
||||
union { void const* ap_pvoid; internal_type const* as_ptype; } caster = { m_storage.address() };
|
||||
return caster.as_ptype;
|
||||
}
|
||||
internal_type * get_object()
|
||||
{
|
||||
union { void* ap_pvoid; internal_type* as_ptype; } caster = { m_storage.address() };
|
||||
return caster.as_ptype;
|
||||
}
|
||||
#else
|
||||
internal_type const* get_object() const { return static_cast<internal_type const*>(m_storage.address()); }
|
||||
internal_type * get_object() { return static_cast<internal_type *> (m_storage.address()); }
|
||||
#endif
|
||||
|
||||
// reference_content<T> lacks an implicit conversion to T&, so the following is needed to obtain a proper reference.
|
||||
reference_const_type dereference( internal_type const* p, is_not_reference_tag ) const { return *p ; }
|
||||
@ -511,12 +556,12 @@ class optional : public optional_detail::optional_base<T>
|
||||
// Depending on the above some T ctor is called.
|
||||
// Can throw is the resolved T ctor throws.
|
||||
template<class Expr>
|
||||
explicit optional ( Expr const& expr ) : base(expr,&expr) {}
|
||||
explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {}
|
||||
#endif
|
||||
|
||||
// Creates a deep copy of another optional<T>
|
||||
// Can throw if T::T(T const&) does
|
||||
optional ( optional const& rhs ) : base(rhs) {}
|
||||
optional ( optional const& rhs ) : base( static_cast<base const&>(rhs) ) {}
|
||||
|
||||
// No-throw (assuming T::~T() doesn't)
|
||||
~optional() {}
|
||||
@ -525,9 +570,9 @@ class optional : public optional_detail::optional_base<T>
|
||||
// Assigns from an expression. See corresponding constructor.
|
||||
// Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
|
||||
template<class Expr>
|
||||
optional& operator= ( Expr expr )
|
||||
optional& operator= ( Expr const& expr )
|
||||
{
|
||||
this->assign_expr(expr,&expr);
|
||||
this->assign_expr(expr,boost::addressof(expr));
|
||||
return *this ;
|
||||
}
|
||||
#endif
|
||||
@ -550,7 +595,7 @@ class optional : public optional_detail::optional_base<T>
|
||||
// (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw)
|
||||
optional& operator= ( optional const& rhs )
|
||||
{
|
||||
this->assign( rhs ) ;
|
||||
this->assign( static_cast<base const&>(rhs) ) ;
|
||||
return *this ;
|
||||
}
|
||||
|
||||
@ -571,6 +616,14 @@ class optional : public optional_detail::optional_base<T>
|
||||
return *this ;
|
||||
}
|
||||
|
||||
void swap( optional & arg )
|
||||
{
|
||||
// allow for Koenig lookup
|
||||
using boost::swap;
|
||||
swap(*this, arg);
|
||||
}
|
||||
|
||||
|
||||
// Returns a reference to the value if this is initialized, otherwise,
|
||||
// the behaviour is UNDEFINED
|
||||
// No-throw
|
||||
@ -580,7 +633,7 @@ class optional : public optional_detail::optional_base<T>
|
||||
// Returns a copy of the value if this is initialized, 'v' otherwise
|
||||
reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; }
|
||||
reference_type get_value_or ( reference_type v ) { return this->is_initialized() ? get() : v ; }
|
||||
|
||||
|
||||
// Returns a pointer to the value if this is initialized, otherwise,
|
||||
// the behaviour is UNDEFINED
|
||||
// No-throw
|
||||
@ -597,22 +650,22 @@ class optional : public optional_detail::optional_base<T>
|
||||
// No-throw
|
||||
operator unspecified_bool_type() const { return this->safe_bool() ; }
|
||||
|
||||
// This is provided for those compilers which don't like the conversion to bool
|
||||
// on some contexts.
|
||||
bool operator!() const { return !this->is_initialized() ; }
|
||||
// This is provided for those compilers which don't like the conversion to bool
|
||||
// on some contexts.
|
||||
bool operator!() const { return !this->is_initialized() ; }
|
||||
} ;
|
||||
|
||||
// Returns optional<T>(v)
|
||||
template<class T>
|
||||
inline
|
||||
template<class T>
|
||||
inline
|
||||
optional<T> make_optional ( T const& v )
|
||||
{
|
||||
return optional<T>(v);
|
||||
}
|
||||
|
||||
// Returns optional<T>(cond,v)
|
||||
template<class T>
|
||||
inline
|
||||
template<class T>
|
||||
inline
|
||||
optional<T> make_optional ( bool cond, T const& v )
|
||||
{
|
||||
return optional<T>(cond,v);
|
||||
@ -865,58 +918,74 @@ inline
|
||||
bool operator >= ( none_t x, optional<T> const& y )
|
||||
{ return !( x < y ) ; }
|
||||
|
||||
//
|
||||
// The following swap implementation follows the GCC workaround as found in
|
||||
// "boost/detail/compressed_pair.hpp"
|
||||
//
|
||||
namespace optional_detail {
|
||||
|
||||
// GCC < 3.2 gets the using declaration at namespace scope (FLC, DWA)
|
||||
#if BOOST_WORKAROUND(__GNUC__, < 3) \
|
||||
|| BOOST_WORKAROUND(__GNUC__, == 3) && __GNUC_MINOR__ <= 2
|
||||
using std::swap;
|
||||
#define BOOST_OPTIONAL_STD_SWAP_INTRODUCED_AT_NS_SCOPE
|
||||
#endif
|
||||
template<bool use_default_constructor> struct swap_selector;
|
||||
|
||||
// optional's swap:
|
||||
// If both are initialized, calls swap(T&, T&). If this swap throws, both will remain initialized but their values are now unspecified.
|
||||
// If only one is initialized, calls U.reset(*I), THEN I.reset().
|
||||
// If U.reset(*I) throws, both are left UNCHANGED (U is kept uinitialized and I is never reset)
|
||||
// If both are uninitialized, do nothing (no-throw)
|
||||
template<class T>
|
||||
inline
|
||||
void optional_swap ( optional<T>& x, optional<T>& y )
|
||||
template<>
|
||||
struct swap_selector<true>
|
||||
{
|
||||
if ( !x && !!y )
|
||||
{
|
||||
x.reset(*y);
|
||||
y.reset();
|
||||
}
|
||||
else if ( !!x && !y )
|
||||
{
|
||||
y.reset(*x);
|
||||
x.reset();
|
||||
}
|
||||
else if ( !!x && !!y )
|
||||
{
|
||||
// GCC > 3.2 and all other compilers have the using declaration at function scope (FLC)
|
||||
#ifndef BOOST_OPTIONAL_STD_SWAP_INTRODUCED_AT_NS_SCOPE
|
||||
// allow for Koenig lookup
|
||||
using std::swap ;
|
||||
#endif
|
||||
swap(*x,*y);
|
||||
}
|
||||
}
|
||||
template<class T>
|
||||
static void optional_swap ( optional<T>& x, optional<T>& y )
|
||||
{
|
||||
const bool hasX = !!x;
|
||||
const bool hasY = !!y;
|
||||
|
||||
if ( !hasX && !hasY )
|
||||
return;
|
||||
|
||||
if( !hasX )
|
||||
x = boost::in_place();
|
||||
else if ( !hasY )
|
||||
y = boost::in_place();
|
||||
|
||||
// Boost.Utility.Swap will take care of ADL and workarounds for broken compilers
|
||||
boost::swap(x.get(),y.get());
|
||||
|
||||
if( !hasX )
|
||||
y = boost::none ;
|
||||
else if( !hasY )
|
||||
x = boost::none ;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct swap_selector<false>
|
||||
{
|
||||
template<class T>
|
||||
static void optional_swap ( optional<T>& x, optional<T>& y )
|
||||
{
|
||||
const bool hasX = !!x;
|
||||
const bool hasY = !!y;
|
||||
|
||||
if ( !hasX && hasY )
|
||||
{
|
||||
x = y.get();
|
||||
y = boost::none ;
|
||||
}
|
||||
else if ( hasX && !hasY )
|
||||
{
|
||||
y = x.get();
|
||||
x = boost::none ;
|
||||
}
|
||||
else if ( hasX && hasY )
|
||||
{
|
||||
// Boost.Utility.Swap will take care of ADL and workarounds for broken compilers
|
||||
boost::swap(x.get(),y.get());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace optional_detail
|
||||
|
||||
template<class T>
|
||||
struct optional_swap_should_use_default_constructor : has_nothrow_default_constructor<T> {} ;
|
||||
|
||||
template<class T> inline void swap ( optional<T>& x, optional<T>& y )
|
||||
{
|
||||
optional_detail::optional_swap(x,y);
|
||||
optional_detail::swap_selector<optional_swap_should_use_default_constructor<T>::value>::optional_swap(x, y);
|
||||
}
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1,14 +1,17 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2003, 2008 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.
|
||||
// See http://www.boost.org/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
// Revisions:
|
||||
// 10 May 2008 (added swap related forward declaration) Niels Dekker
|
||||
//
|
||||
#ifndef BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP
|
||||
#define BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP
|
||||
|
||||
@ -16,6 +19,10 @@ namespace boost {
|
||||
|
||||
template<class T> class optional ;
|
||||
|
||||
template<class T> void swap ( optional<T>& , optional<T>& ) ;
|
||||
|
||||
template<class T> struct optional_swap_should_use_default_constructor ;
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
@ -4,7 +4,7 @@
|
||||
// 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.
|
||||
// See http://www.boost.org/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
@ -13,19 +13,20 @@
|
||||
#define BOOST_OPTIONAL_OPTIONAL_IO_FLC_19NOV2002_HPP
|
||||
|
||||
#if defined __GNUC__
|
||||
# if (__GNUC__ == 2 && __GNUC_MINOR__ <= 97)
|
||||
# if (__GNUC__ == 2 && __GNUC_MINOR__ <= 97)
|
||||
# define BOOST_OPTIONAL_NO_TEMPLATED_STREAMS
|
||||
# endif
|
||||
#endif // __GNUC__
|
||||
|
||||
#if defined BOOST_OPTIONAL_NO_TEMPLATED_STREAMS
|
||||
# include <iostream>
|
||||
#else
|
||||
#else
|
||||
# include <istream>
|
||||
# include <ostream>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include <boost/none.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include "boost/optional/optional.hpp"
|
||||
#include "boost/utility/value_init.hpp"
|
||||
|
||||
@ -62,17 +63,30 @@ std::basic_istream<CharType, CharTrait>&
|
||||
operator>>(std::basic_istream<CharType, CharTrait>& in, optional<T>& v)
|
||||
#endif
|
||||
{
|
||||
if ( in.good() )
|
||||
if (in.good())
|
||||
{
|
||||
int d = in.get();
|
||||
if ( d == ' ' )
|
||||
if (d == ' ')
|
||||
{
|
||||
T x ;
|
||||
T x;
|
||||
in >> x;
|
||||
v = x ;
|
||||
v = x;
|
||||
}
|
||||
else
|
||||
v = optional<T>() ;
|
||||
{
|
||||
if (d == '-')
|
||||
{
|
||||
d = in.get();
|
||||
|
||||
if (d == '-')
|
||||
{
|
||||
v = none;
|
||||
return in;
|
||||
}
|
||||
}
|
||||
|
||||
in.setstate( std::ios::failbit );
|
||||
}
|
||||
}
|
||||
|
||||
return in;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2003, 2008 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
|
||||
@ -9,6 +9,9 @@
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
// Revisions:
|
||||
// 12 May 2008 (added more swap tests)
|
||||
//
|
||||
#include<iostream>
|
||||
#include<stdexcept>
|
||||
#include<string>
|
||||
@ -16,6 +19,8 @@
|
||||
#define BOOST_ENABLE_ASSERT_HANDLER
|
||||
|
||||
#include "boost/bind/apply.hpp" // Included just to test proper interaction with boost::apply<> as reported by Daniel Wallin
|
||||
#include "boost/mpl/bool.hpp"
|
||||
#include "boost/mpl/bool_fwd.hpp" // For mpl::true_ and mpl::false_
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
@ -153,27 +158,27 @@ void test_basics( T const* )
|
||||
ob.reset();
|
||||
check_is_pending_dtor( ARG(T) ) ;
|
||||
check_uninitialized(ob);
|
||||
|
||||
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void test_conditional_ctor_and_get_valur_or ( T const* )
|
||||
{
|
||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||
|
||||
|
||||
T a(321);
|
||||
|
||||
|
||||
T z(123);
|
||||
|
||||
|
||||
optional<T> const cdef0(false,a);
|
||||
|
||||
|
||||
optional<T> def0(false,a);
|
||||
optional<T> def1 = boost::make_optional(false,a); // T is not within boost so ADL won't find make_optional unqualified
|
||||
check_uninitialized(def0);
|
||||
check_uninitialized(def1);
|
||||
|
||||
optional<T> const co0(true,a);
|
||||
|
||||
|
||||
optional<T> o0(true,a);
|
||||
optional<T> o1 = boost::make_optional(true,a); // T is not within boost so ADL won't find make_optional unqualified
|
||||
|
||||
@ -181,65 +186,65 @@ void test_conditional_ctor_and_get_valur_or ( T const* )
|
||||
check_initialized(o1);
|
||||
check_value(o0,a,z);
|
||||
check_value(o1,a,z);
|
||||
|
||||
|
||||
T b = def0.get_value_or(z);
|
||||
BOOST_CHECK( b == z ) ;
|
||||
|
||||
|
||||
b = get_optional_value_or(def0,z);
|
||||
BOOST_CHECK( b == z ) ;
|
||||
|
||||
|
||||
b = o0.get_value_or(z);
|
||||
BOOST_CHECK( b == a ) ;
|
||||
|
||||
b = get_optional_value_or(o0,z);
|
||||
BOOST_CHECK( b == a ) ;
|
||||
|
||||
|
||||
|
||||
|
||||
T const& crz = z ;
|
||||
T& rz = z ;
|
||||
|
||||
|
||||
T const& crzz = def0.get_value_or(crz);
|
||||
BOOST_CHECK( crzz == crz ) ;
|
||||
|
||||
|
||||
T& rzz = def0.get_value_or(rz);
|
||||
BOOST_CHECK( rzz == rz ) ;
|
||||
|
||||
|
||||
T const& crzzz = get_optional_value_or(cdef0,crz);
|
||||
BOOST_CHECK( crzzz == crz ) ;
|
||||
|
||||
|
||||
T& rzzz = get_optional_value_or(def0,rz);
|
||||
BOOST_CHECK( rzzz == rz ) ;
|
||||
|
||||
|
||||
T const& crb = o0.get_value_or(crz);
|
||||
BOOST_CHECK( crb == a ) ;
|
||||
|
||||
|
||||
T& rb = o0.get_value_or(rz);
|
||||
BOOST_CHECK( rb == b ) ;
|
||||
|
||||
|
||||
T const& crbb = get_optional_value_or(co0,crz);
|
||||
BOOST_CHECK( crbb == b ) ;
|
||||
|
||||
|
||||
T const& crbbb = get_optional_value_or(o0,crz);
|
||||
BOOST_CHECK( crbbb == b ) ;
|
||||
|
||||
|
||||
T& rbb = get_optional_value_or(o0,rz);
|
||||
BOOST_CHECK( rbb == b ) ;
|
||||
|
||||
|
||||
T& ra = a ;
|
||||
|
||||
|
||||
optional<T&> defref(false,ra);
|
||||
BOOST_CHECK(!defref);
|
||||
|
||||
|
||||
optional<T&> ref(true,ra);
|
||||
BOOST_CHECK(!!ref);
|
||||
|
||||
|
||||
a = T(432);
|
||||
|
||||
|
||||
BOOST_CHECK( *ref == a ) ;
|
||||
|
||||
|
||||
T& r1 = defref.get_value_or(z);
|
||||
BOOST_CHECK( r1 == z ) ;
|
||||
|
||||
|
||||
T& r2 = ref.get_value_or(z);
|
||||
BOOST_CHECK( r2 == a ) ;
|
||||
}
|
||||
@ -713,7 +718,7 @@ void test_relops( T const* )
|
||||
optional<T> opt0(v0);
|
||||
optional<T> opt1(v1);
|
||||
optional<T> opt2(v2);
|
||||
|
||||
|
||||
// Check identity
|
||||
BOOST_CHECK ( def0 == def0 ) ;
|
||||
BOOST_CHECK ( opt0 == opt0 ) ;
|
||||
@ -751,7 +756,7 @@ void test_relops( T const* )
|
||||
BOOST_CHECK ( opt1 > opt0 ) ;
|
||||
BOOST_CHECK ( opt1 <= opt2 ) ;
|
||||
BOOST_CHECK ( opt1 >= opt0 ) ;
|
||||
|
||||
|
||||
// Compare against a value directly
|
||||
BOOST_CHECK ( opt0 == v0 ) ;
|
||||
BOOST_CHECK ( opt0 != v1 ) ;
|
||||
@ -794,7 +799,7 @@ void test_none( T const* )
|
||||
BOOST_CHECK ( def0 == none ) ;
|
||||
BOOST_CHECK ( non_def != none ) ;
|
||||
BOOST_CHECK ( !def1 ) ;
|
||||
BOOST_CHECK ( !(non_def < none) ) ;
|
||||
BOOST_CHECK ( !(non_def < none) ) ;
|
||||
BOOST_CHECK ( non_def > none ) ;
|
||||
BOOST_CHECK ( !(non_def <= none) ) ;
|
||||
BOOST_CHECK ( non_def >= none ) ;
|
||||
@ -814,11 +819,11 @@ void test_arrow( T const* )
|
||||
|
||||
optional<T> oa(a) ;
|
||||
optional<T> const coa(a) ;
|
||||
|
||||
|
||||
BOOST_CHECK ( coa->V() == 1234 ) ;
|
||||
|
||||
|
||||
oa->V() = 4321 ;
|
||||
|
||||
|
||||
BOOST_CHECK ( a.V() = 1234 ) ;
|
||||
BOOST_CHECK ( (*oa).V() = 4321 ) ;
|
||||
}
|
||||
@ -927,6 +932,364 @@ void test_conversions2()
|
||||
BOOST_CHECK(*get(&opt1) == static_cast<double>(f));
|
||||
}
|
||||
|
||||
|
||||
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_CHECK(!"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_CHECK(!"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_CHECK(!"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_CHECK(!"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_CHECK(!"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_CHECK(!"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>
|
||||
bool test_swap_function( T const* )
|
||||
{
|
||||
const boost::unit_test::counter_t counter_before_test = boost::minimal_test::errors_counter();
|
||||
try
|
||||
{
|
||||
optional<T> obj1;
|
||||
optional<T> obj2('a');
|
||||
|
||||
// Self-swap should not have any effect.
|
||||
swap(obj1, obj1);
|
||||
swap(obj2, obj2);
|
||||
BOOST_CHECK(!obj1);
|
||||
BOOST_CHECK(!!obj2 && obj2->data == 'a');
|
||||
|
||||
// Call non-member swap.
|
||||
swap(obj1, obj2);
|
||||
|
||||
// Test if obj1 and obj2 are really swapped.
|
||||
BOOST_CHECK(!!obj1 && obj1->data == 'a');
|
||||
BOOST_CHECK(!obj2);
|
||||
|
||||
// Call non-member swap one more time.
|
||||
swap(obj1, obj2);
|
||||
|
||||
// Test if obj1 and obj2 are swapped back.
|
||||
BOOST_CHECK(!obj1);
|
||||
BOOST_CHECK(!!obj2 && obj2->data == 'a');
|
||||
}
|
||||
catch(const std::exception &)
|
||||
{
|
||||
// The swap function should not throw, for our test cases.
|
||||
return false ;
|
||||
}
|
||||
return boost::minimal_test::errors_counter() == counter_before_test ;
|
||||
}
|
||||
|
||||
//
|
||||
// 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>
|
||||
bool test_swap_member_function( T const* )
|
||||
{
|
||||
const boost::unit_test::counter_t counter_before_test = boost::minimal_test::errors_counter();
|
||||
try
|
||||
{
|
||||
optional<T> obj1;
|
||||
optional<T> obj2('a');
|
||||
|
||||
// Self-swap should not have any effect.
|
||||
obj1.swap(obj1);
|
||||
obj2.swap(obj2);
|
||||
BOOST_CHECK(!obj1);
|
||||
BOOST_CHECK(!!obj2 && obj2->data == 'a');
|
||||
|
||||
// Call member swap.
|
||||
obj1.swap(obj2);
|
||||
|
||||
// Test if obj1 and obj2 are really swapped.
|
||||
BOOST_CHECK(!!obj1 && obj1->data == 'a');
|
||||
BOOST_CHECK(!obj2);
|
||||
|
||||
// Call member swap one more time.
|
||||
obj1.swap(obj2);
|
||||
|
||||
// Test if obj1 and obj2 are swapped back.
|
||||
BOOST_CHECK(!obj1);
|
||||
BOOST_CHECK(!!obj2 && obj2->data == 'a');
|
||||
}
|
||||
catch(const std::exception &)
|
||||
{
|
||||
// The optional<T>::swap member function should not throw, for our test cases.
|
||||
return false ;
|
||||
}
|
||||
return boost::minimal_test::errors_counter() == counter_before_test ;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Tests compile time tweaking of swap, by means of
|
||||
// optional_swap_should_use_default_constructor.
|
||||
//
|
||||
void test_swap_tweaking()
|
||||
{
|
||||
BOOST_CHECK( test_swap_function( ARG(optional_swap_test::class_without_default_ctor) ) );
|
||||
BOOST_CHECK( test_swap_function( ARG(optional_swap_test::class_whose_default_ctor_should_be_used) ) );
|
||||
BOOST_CHECK( test_swap_function( ARG(optional_swap_test::class_whose_default_ctor_should_not_be_used) ) );
|
||||
BOOST_CHECK( test_swap_function( ARG(optional_swap_test::class_whose_explicit_ctor_should_be_used) ) );
|
||||
BOOST_CHECK( test_swap_function( ARG(optional_swap_test::template_whose_default_ctor_should_be_used<char>) ) );
|
||||
BOOST_CHECK( test_swap_member_function( ARG(optional_swap_test::class_without_default_ctor) ) );
|
||||
BOOST_CHECK( test_swap_member_function( ARG(optional_swap_test::class_whose_default_ctor_should_be_used) ) );
|
||||
BOOST_CHECK( test_swap_member_function( ARG(optional_swap_test::class_whose_default_ctor_should_not_be_used) ) );
|
||||
BOOST_CHECK( test_swap_member_function( ARG(optional_swap_test::class_whose_explicit_ctor_should_be_used) ) );
|
||||
BOOST_CHECK( test_swap_member_function( ARG(optional_swap_test::template_whose_default_ctor_should_be_used<char>) ) );
|
||||
}
|
||||
|
||||
// Test for support for classes with overridden operator&
|
||||
class CustomAddressOfClass
|
||||
{
|
||||
int n;
|
||||
|
||||
public:
|
||||
CustomAddressOfClass() : n(0) {}
|
||||
CustomAddressOfClass(CustomAddressOfClass const& that) : n(that.n) {}
|
||||
explicit CustomAddressOfClass(int m) : n(m) {}
|
||||
int* operator& () { return &n; }
|
||||
bool operator== (CustomAddressOfClass const& that) const { return n == that.n; }
|
||||
};
|
||||
|
||||
void test_custom_addressof_operator()
|
||||
{
|
||||
boost::optional< CustomAddressOfClass > o1(CustomAddressOfClass(10));
|
||||
BOOST_CHECK(!!o1);
|
||||
BOOST_CHECK(o1.get() == CustomAddressOfClass(10));
|
||||
|
||||
o1 = CustomAddressOfClass(20);
|
||||
BOOST_CHECK(!!o1);
|
||||
BOOST_CHECK(o1.get() == CustomAddressOfClass(20));
|
||||
|
||||
o1 = boost::none;
|
||||
BOOST_CHECK(!o1);
|
||||
}
|
||||
|
||||
int test_main( int, char* [] )
|
||||
{
|
||||
try
|
||||
@ -936,6 +1299,8 @@ int test_main( int, char* [] )
|
||||
test_no_implicit_conversions();
|
||||
test_conversions1();
|
||||
test_conversions2();
|
||||
test_swap_tweaking();
|
||||
test_custom_addressof_operator();
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
|
@ -55,10 +55,14 @@ void test2( Opt o, Opt buff )
|
||||
{
|
||||
stringstream s ;
|
||||
|
||||
s << o ;
|
||||
s >> buff ;
|
||||
const int markv = 123 ;
|
||||
int mark = 0 ;
|
||||
|
||||
s << o << " " << markv ;
|
||||
s >> buff >> mark ;
|
||||
|
||||
BOOST_ASSERT( buff == o ) ;
|
||||
BOOST_ASSERT( mark == markv ) ;
|
||||
}
|
||||
|
||||
|
||||
@ -77,7 +81,6 @@ int test_main( int, char* [] )
|
||||
{
|
||||
test(1,2);
|
||||
test(string("hello"),string("buffer"));
|
||||
test(string(""),string("buffer"));
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
|
Reference in New Issue
Block a user