mirror of
https://github.com/boostorg/optional.git
synced 2025-06-29 14:01:07 +02:00
Compare commits
1 Commits
svn-branch
...
svn-branch
Author | SHA1 | Date | |
---|---|---|---|
da8f2d028e |
@ -24,7 +24,7 @@ boostbook standalone
|
|||||||
optional
|
optional
|
||||||
:
|
:
|
||||||
<xsl:param>boost.root=../../../..
|
<xsl:param>boost.root=../../../..
|
||||||
<xsl:param>html.stylesheet=boostbook.css
|
<xsl:param>boost.libraries=../../../libraries.htm
|
||||||
<xsl:param>toc.max.depth=2
|
<xsl:param>toc.max.depth=2
|
||||||
<xsl:param>toc.section.depth=2
|
<xsl:param>toc.section.depth=2
|
||||||
<xsl:param>chunk.section.depth=1
|
<xsl:param>chunk.section.depth=1
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
// http://www.boost.org/LICENSE_1_0.txt)
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
//
|
//
|
||||||
// See http://www.boost.org/libs/optional for documentation.
|
// See http://www.boost.org/lib/optional for documentation.
|
||||||
//
|
//
|
||||||
// You are welcome to contact the author at:
|
// You are welcome to contact the author at:
|
||||||
// fernando_cacciola@hotmail.com
|
// fernando_cacciola@hotmail.com
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
// http://www.boost.org/LICENSE_1_0.txt)
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
//
|
//
|
||||||
// See http://www.boost.org/libs/optional for documentation.
|
// See http://www.boost.org/lib/optional for documentation.
|
||||||
//
|
//
|
||||||
// You are welcome to contact the author at:
|
// You are welcome to contact the author at:
|
||||||
// fernando_cacciola@hotmail.com
|
// fernando_cacciola@hotmail.com
|
||||||
@ -18,25 +18,23 @@
|
|||||||
#include<new>
|
#include<new>
|
||||||
#include<algorithm>
|
#include<algorithm>
|
||||||
|
|
||||||
#include <boost/config.hpp>
|
#include "boost/config.hpp"
|
||||||
#include <boost/assert.hpp>
|
#include "boost/assert.hpp"
|
||||||
#include <boost/type.hpp>
|
#include "boost/type.hpp"
|
||||||
#include <boost/type_traits/alignment_of.hpp>
|
#include "boost/type_traits/alignment_of.hpp"
|
||||||
#include <boost/type_traits/has_nothrow_constructor.hpp>
|
#include "boost/type_traits/has_nothrow_constructor.hpp"
|
||||||
#include <boost/type_traits/type_with_alignment.hpp>
|
#include "boost/type_traits/type_with_alignment.hpp"
|
||||||
#include <boost/type_traits/remove_reference.hpp>
|
#include "boost/type_traits/remove_reference.hpp"
|
||||||
#include <boost/type_traits/is_reference.hpp>
|
#include "boost/type_traits/is_reference.hpp"
|
||||||
#include <boost/mpl/if.hpp>
|
#include "boost/mpl/if.hpp"
|
||||||
#include <boost/mpl/bool.hpp>
|
#include "boost/mpl/bool.hpp"
|
||||||
#include <boost/mpl/not.hpp>
|
#include "boost/mpl/not.hpp"
|
||||||
#include <boost/detail/reference_content.hpp>
|
#include "boost/detail/reference_content.hpp"
|
||||||
#include <boost/none.hpp>
|
#include "boost/none.hpp"
|
||||||
#include <boost/utility/swap.hpp>
|
#include "boost/utility/compare_pointees.hpp"
|
||||||
#include <boost/utility/addressof.hpp>
|
#include "boost/utility/in_place_factory.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)
|
#if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
|
||||||
// VC6.0 has the following bug:
|
// VC6.0 has the following bug:
|
||||||
@ -83,15 +81,6 @@
|
|||||||
#define BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
|
#define BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
|
||||||
#endif
|
#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<>
|
// Daniel Wallin discovered that bind/apply.hpp badly interacts with the apply<>
|
||||||
// member template of a factory as used in the optional<> implementation.
|
// 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
|
// He proposed this simple fix which is to move the call to apply<> outside
|
||||||
@ -99,7 +88,7 @@
|
|||||||
namespace boost_optional_detail
|
namespace boost_optional_detail
|
||||||
{
|
{
|
||||||
template <class T, class Factory>
|
template <class T, class Factory>
|
||||||
inline void construct(Factory const& factory, void* address)
|
void construct(Factory const& factory, void* address)
|
||||||
{
|
{
|
||||||
factory.BOOST_NESTED_TEMPLATE apply<T>(address);
|
factory.BOOST_NESTED_TEMPLATE apply<T>(address);
|
||||||
}
|
}
|
||||||
@ -111,9 +100,6 @@ namespace boost {
|
|||||||
class in_place_factory_base ;
|
class in_place_factory_base ;
|
||||||
class typed_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 {
|
namespace optional_detail {
|
||||||
|
|
||||||
// This local class is used instead of that in "aligned_storage.hpp"
|
// This local class is used instead of that in "aligned_storage.hpp"
|
||||||
@ -124,12 +110,7 @@ template <class T>
|
|||||||
class aligned_storage
|
class aligned_storage
|
||||||
{
|
{
|
||||||
// Borland ICEs if unnamed unions are used for this!
|
// Borland ICEs if unnamed unions are used for this!
|
||||||
union
|
union dummy_u
|
||||||
// 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) ];
|
char data[ sizeof(T) ];
|
||||||
BOOST_DEDUCED_TYPENAME type_with_alignment<
|
BOOST_DEDUCED_TYPENAME type_with_alignment<
|
||||||
@ -138,13 +119,8 @@ class aligned_storage
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
|
void const* address() const { return &dummy_.data[0]; }
|
||||||
void const* address() const { return &dummy_; }
|
void * address() { return &dummy_.data[0]; }
|
||||||
void * address() { return &dummy_; }
|
|
||||||
#else
|
|
||||||
void const* address() const { return dummy_.data; }
|
|
||||||
void * address() { return dummy_.data; }
|
|
||||||
#endif
|
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
@ -450,22 +426,8 @@ class optional_base : public optional_tag
|
|||||||
private :
|
private :
|
||||||
|
|
||||||
// internal_type can be either T or reference_content<T>
|
// 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 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()); }
|
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_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 ; }
|
reference_const_type dereference( internal_type const* p, is_not_reference_tag ) const { return *p ; }
|
||||||
@ -556,7 +518,7 @@ class optional : public optional_detail::optional_base<T>
|
|||||||
// Depending on the above some T ctor is called.
|
// Depending on the above some T ctor is called.
|
||||||
// Can throw is the resolved T ctor throws.
|
// Can throw is the resolved T ctor throws.
|
||||||
template<class Expr>
|
template<class Expr>
|
||||||
explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {}
|
explicit optional ( Expr const& expr ) : base(expr,&expr) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Creates a deep copy of another optional<T>
|
// Creates a deep copy of another optional<T>
|
||||||
@ -570,9 +532,9 @@ class optional : public optional_detail::optional_base<T>
|
|||||||
// Assigns from an expression. See corresponding constructor.
|
// Assigns from an expression. See corresponding constructor.
|
||||||
// Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
|
// Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
|
||||||
template<class Expr>
|
template<class Expr>
|
||||||
optional& operator= ( Expr const& expr )
|
optional& operator= ( Expr expr )
|
||||||
{
|
{
|
||||||
this->assign_expr(expr,boost::addressof(expr));
|
this->assign_expr(expr,&expr);
|
||||||
return *this ;
|
return *this ;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -918,8 +880,19 @@ inline
|
|||||||
bool operator >= ( none_t x, optional<T> const& y )
|
bool operator >= ( none_t x, optional<T> const& y )
|
||||||
{ return !( x < y ) ; }
|
{ return !( x < y ) ; }
|
||||||
|
|
||||||
|
//
|
||||||
|
// The following swap implementation follows the GCC workaround as found in
|
||||||
|
// "boost/detail/compressed_pair.hpp"
|
||||||
|
//
|
||||||
namespace optional_detail {
|
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;
|
template<bool use_default_constructor> struct swap_selector;
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
@ -928,8 +901,8 @@ struct swap_selector<true>
|
|||||||
template<class T>
|
template<class T>
|
||||||
static void optional_swap ( optional<T>& x, optional<T>& y )
|
static void optional_swap ( optional<T>& x, optional<T>& y )
|
||||||
{
|
{
|
||||||
const bool hasX = !!x;
|
bool hasX = x;
|
||||||
const bool hasY = !!y;
|
bool hasY = y;
|
||||||
|
|
||||||
if ( !hasX && !hasY )
|
if ( !hasX && !hasY )
|
||||||
return;
|
return;
|
||||||
@ -939,8 +912,12 @@ struct swap_selector<true>
|
|||||||
else if ( !hasY )
|
else if ( !hasY )
|
||||||
y = boost::in_place();
|
y = boost::in_place();
|
||||||
|
|
||||||
// Boost.Utility.Swap will take care of ADL and workarounds for broken compilers
|
// GCC > 3.2 and all other compilers have the using declaration at function scope (FLC)
|
||||||
boost::swap(x.get(),y.get());
|
#ifndef BOOST_OPTIONAL_STD_SWAP_INTRODUCED_AT_NS_SCOPE
|
||||||
|
// allow for Koenig lookup
|
||||||
|
using std::swap ;
|
||||||
|
#endif
|
||||||
|
swap(*x,*y);
|
||||||
|
|
||||||
if( !hasX )
|
if( !hasX )
|
||||||
y = boost::none ;
|
y = boost::none ;
|
||||||
@ -955,23 +932,24 @@ struct swap_selector<false>
|
|||||||
template<class T>
|
template<class T>
|
||||||
static void optional_swap ( optional<T>& x, optional<T>& y )
|
static void optional_swap ( optional<T>& x, optional<T>& y )
|
||||||
{
|
{
|
||||||
const bool hasX = !!x;
|
if ( !x && !!y )
|
||||||
const bool hasY = !!y;
|
|
||||||
|
|
||||||
if ( !hasX && hasY )
|
|
||||||
{
|
{
|
||||||
x = y.get();
|
x = *y;
|
||||||
y = boost::none ;
|
y = boost::none ;
|
||||||
}
|
}
|
||||||
else if ( hasX && !hasY )
|
else if ( !!x && !y )
|
||||||
{
|
{
|
||||||
y = x.get();
|
y = *x ;
|
||||||
x = boost::none ;
|
x = boost::none ;
|
||||||
}
|
}
|
||||||
else if ( hasX && hasY )
|
else if ( !!x && !!y )
|
||||||
{
|
{
|
||||||
// Boost.Utility.Swap will take care of ADL and workarounds for broken compilers
|
// GCC > 3.2 and all other compilers have the using declaration at function scope (FLC)
|
||||||
boost::swap(x.get(),y.get());
|
#ifndef BOOST_OPTIONAL_STD_SWAP_INTRODUCED_AT_NS_SCOPE
|
||||||
|
// allow for Koenig lookup
|
||||||
|
using std::swap ;
|
||||||
|
#endif
|
||||||
|
swap(*x,*y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -989,3 +967,4 @@ template<class T> inline void swap ( optional<T>& x, optional<T>& y )
|
|||||||
} // namespace boost
|
} // namespace boost
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
// http://www.boost.org/LICENSE_1_0.txt)
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
//
|
//
|
||||||
// See http://www.boost.org/libs/optional for documentation.
|
// See http://www.boost.org/lib/optional for documentation.
|
||||||
//
|
//
|
||||||
// You are welcome to contact the author at:
|
// You are welcome to contact the author at:
|
||||||
// fernando_cacciola@hotmail.com
|
// fernando_cacciola@hotmail.com
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
// http://www.boost.org/LICENSE_1_0.txt)
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
//
|
//
|
||||||
// See http://www.boost.org/libs/optional for documentation.
|
// See http://www.boost.org/lib/optional for documentation.
|
||||||
//
|
//
|
||||||
// You are welcome to contact the author at:
|
// You are welcome to contact the author at:
|
||||||
// fernando_cacciola@hotmail.com
|
// fernando_cacciola@hotmail.com
|
||||||
@ -25,8 +25,7 @@
|
|||||||
# include <ostream>
|
# include <ostream>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <boost/none.hpp>
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
#include "boost/optional/optional.hpp"
|
#include "boost/optional/optional.hpp"
|
||||||
#include "boost/utility/value_init.hpp"
|
#include "boost/utility/value_init.hpp"
|
||||||
|
|
||||||
@ -73,20 +72,7 @@ operator>>(std::basic_istream<CharType, CharTrait>& in, optional<T>& v)
|
|||||||
v = x ;
|
v = x ;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
v = optional<T>() ;
|
||||||
if (d == '-')
|
|
||||||
{
|
|
||||||
d = in.get();
|
|
||||||
|
|
||||||
if (d == '-')
|
|
||||||
{
|
|
||||||
v = none;
|
|
||||||
return in;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
in.setstate( std::ios::failbit );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return in;
|
return in;
|
||||||
|
@ -1263,33 +1263,6 @@ void test_swap_tweaking()
|
|||||||
BOOST_CHECK( test_swap_member_function( ARG(optional_swap_test::template_whose_default_ctor_should_be_used<char>) ) );
|
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* [] )
|
int test_main( int, char* [] )
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -1300,7 +1273,6 @@ int test_main( int, char* [] )
|
|||||||
test_conversions1();
|
test_conversions1();
|
||||||
test_conversions2();
|
test_conversions2();
|
||||||
test_swap_tweaking();
|
test_swap_tweaking();
|
||||||
test_custom_addressof_operator();
|
|
||||||
}
|
}
|
||||||
catch ( ... )
|
catch ( ... )
|
||||||
{
|
{
|
||||||
|
@ -55,14 +55,10 @@ void test2( Opt o, Opt buff )
|
|||||||
{
|
{
|
||||||
stringstream s ;
|
stringstream s ;
|
||||||
|
|
||||||
const int markv = 123 ;
|
s << o ;
|
||||||
int mark = 0 ;
|
s >> buff ;
|
||||||
|
|
||||||
s << o << " " << markv ;
|
|
||||||
s >> buff >> mark ;
|
|
||||||
|
|
||||||
BOOST_ASSERT( buff == o ) ;
|
BOOST_ASSERT( buff == o ) ;
|
||||||
BOOST_ASSERT( mark == markv ) ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -81,6 +77,7 @@ int test_main( int, char* [] )
|
|||||||
{
|
{
|
||||||
test(1,2);
|
test(1,2);
|
||||||
test(string("hello"),string("buffer"));
|
test(string("hello"),string("buffer"));
|
||||||
|
test(string(""),string("buffer"));
|
||||||
}
|
}
|
||||||
catch ( ... )
|
catch ( ... )
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user