diff --git a/include/boost/smart_ptr/detail/operator_bool.hpp b/include/boost/smart_ptr/detail/operator_bool.hpp index e38593f..8ae1527 100644 --- a/include/boost/smart_ptr/detail/operator_bool.hpp +++ b/include/boost/smart_ptr/detail/operator_bool.hpp @@ -1,12 +1,19 @@ // This header intentionally has no include guards. // -// Copyright (c) 2001-2009 Peter Dimov +// Copyright (c) 2001-2009, 2012 Peter Dimov // // Distributed under 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 -#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__) +#if !defined( BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS ) && !defined( BOOST_NO_CXX11_NULLPTR ) + + explicit operator bool () const BOOST_NOEXCEPT + { + return px != 0; + } + +#elif ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__) operator bool () const BOOST_NOEXCEPT { diff --git a/include/boost/smart_ptr/intrusive_ptr.hpp b/include/boost/smart_ptr/intrusive_ptr.hpp index 01e2429..ffb2dba 100644 --- a/include/boost/smart_ptr/intrusive_ptr.hpp +++ b/include/boost/smart_ptr/intrusive_ptr.hpp @@ -218,6 +218,30 @@ template inline bool operator!=(intrusive_ptr const & a, intrusive_p #endif +#if !defined( BOOST_NO_CXX11_NULLPTR ) + +template inline bool operator==( intrusive_ptr const & p, std::nullptr_t ) BOOST_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator==( std::nullptr_t, intrusive_ptr const & p ) BOOST_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator!=( intrusive_ptr const & p, std::nullptr_t ) BOOST_NOEXCEPT +{ + return p.get() != 0; +} + +template inline bool operator!=( std::nullptr_t, intrusive_ptr const & p ) BOOST_NOEXCEPT +{ + return p.get() != 0; +} + +#endif + template inline bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) { return std::less()(a.get(), b.get()); diff --git a/include/boost/smart_ptr/scoped_array.hpp b/include/boost/smart_ptr/scoped_array.hpp index 83352e2..1ddaa07 100644 --- a/include/boost/smart_ptr/scoped_array.hpp +++ b/include/boost/smart_ptr/scoped_array.hpp @@ -11,6 +11,7 @@ // http://www.boost.org/libs/smart_ptr/scoped_array.htm // +#include #include #include #include // in case ptrdiff_t not in std @@ -97,6 +98,30 @@ public: } }; +#if !defined( BOOST_NO_CXX11_NULLPTR ) + +template inline bool operator==( scoped_array const & p, std::nullptr_t ) BOOST_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator==( std::nullptr_t, scoped_array const & p ) BOOST_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator!=( scoped_array const & p, std::nullptr_t ) BOOST_NOEXCEPT +{ + return p.get() != 0; +} + +template inline bool operator!=( std::nullptr_t, scoped_array const & p ) BOOST_NOEXCEPT +{ + return p.get() != 0; +} + +#endif + template inline void swap(scoped_array & a, scoped_array & b) BOOST_NOEXCEPT { a.swap(b); diff --git a/include/boost/smart_ptr/scoped_ptr.hpp b/include/boost/smart_ptr/scoped_ptr.hpp index 3ccf697..a75f91f 100644 --- a/include/boost/smart_ptr/scoped_ptr.hpp +++ b/include/boost/smart_ptr/scoped_ptr.hpp @@ -11,6 +11,7 @@ // http://www.boost.org/libs/smart_ptr/scoped_ptr.htm // +#include #include #include #include @@ -114,6 +115,30 @@ public: } }; +#if !defined( BOOST_NO_CXX11_NULLPTR ) + +template inline bool operator==( scoped_ptr const & p, std::nullptr_t ) BOOST_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator==( std::nullptr_t, scoped_ptr const & p ) BOOST_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator!=( scoped_ptr const & p, std::nullptr_t ) BOOST_NOEXCEPT +{ + return p.get() != 0; +} + +template inline bool operator!=( std::nullptr_t, scoped_ptr const & p ) BOOST_NOEXCEPT +{ + return p.get() != 0; +} + +#endif + template inline void swap(scoped_ptr & a, scoped_ptr & b) BOOST_NOEXCEPT { a.swap(b); diff --git a/include/boost/smart_ptr/shared_array.hpp b/include/boost/smart_ptr/shared_array.hpp index ac64099..f54f481 100644 --- a/include/boost/smart_ptr/shared_array.hpp +++ b/include/boost/smart_ptr/shared_array.hpp @@ -243,6 +243,30 @@ template inline bool operator!=(shared_array const & a, shared_array return a.get() != b.get(); } +#if !defined( BOOST_NO_CXX11_NULLPTR ) + +template inline bool operator==( shared_array const & p, std::nullptr_t ) BOOST_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator==( std::nullptr_t, shared_array const & p ) BOOST_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator!=( shared_array const & p, std::nullptr_t ) BOOST_NOEXCEPT +{ + return p.get() != 0; +} + +template inline bool operator!=( std::nullptr_t, shared_array const & p ) BOOST_NOEXCEPT +{ + return p.get() != 0; +} + +#endif + template inline bool operator<(shared_array const & a, shared_array const & b) BOOST_NOEXCEPT { return std::less()(a.get(), b.get()); diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index e472d12..3b1ac79 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -41,7 +41,7 @@ #include // for std::swap #include // for std::less #include // for std::bad_cast -#include // for std::size_t +#include // for std::size_t, std::nullptr_t #if !defined(BOOST_NO_IOSTREAM) #if !defined(BOOST_NO_IOSFWD) @@ -339,6 +339,14 @@ public: { } +#if !defined( BOOST_NO_CXX11_NULLPTR ) + + shared_ptr( std::nullptr_t ) BOOST_NOEXCEPT : px( 0 ), pn() // never throws + { + } + +#endif + template explicit shared_ptr( Y * p ): px( p ), pn() // Y must be complete { @@ -356,6 +364,14 @@ public: boost::detail::sp_deleter_construct( this, p ); } +#if !defined( BOOST_NO_CXX11_NULLPTR ) + + template shared_ptr( std::nullptr_t p, D d ): px( p ), pn( p, d ) + { + } + +#endif + // As above, but with allocator. A's copy constructor shall not throw. template shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a ) @@ -363,6 +379,14 @@ public: boost::detail::sp_deleter_construct( this, p ); } +#if !defined( BOOST_NO_CXX11_NULLPTR ) + + template shared_ptr( std::nullptr_t p, D d, A a ): px( p ), pn( p, d, a ) + { + } + +#endif + // generated copy constructor, destructor are fine... #if defined( BOOST_HAS_RVALUE_REFS ) @@ -577,6 +601,16 @@ public: return *this; } +#endif + +#if !defined( BOOST_NO_CXX11_NULLPTR ) + + shared_ptr & operator=( std::nullptr_t ) BOOST_NOEXCEPT // never throws + { + this_type().swap(*this); + return *this; + } + #endif void reset() BOOST_NOEXCEPT // never throws in 1.30+ @@ -711,6 +745,30 @@ template inline bool operator!=(shared_ptr const & a, shared_ptr #endif +#if !defined( BOOST_NO_CXX11_NULLPTR ) + +template inline bool operator==( shared_ptr const & p, std::nullptr_t ) BOOST_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator==( std::nullptr_t, shared_ptr const & p ) BOOST_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator!=( shared_ptr const & p, std::nullptr_t ) BOOST_NOEXCEPT +{ + return p.get() != 0; +} + +template inline bool operator!=( std::nullptr_t, shared_ptr const & p ) BOOST_NOEXCEPT +{ + return p.get() != 0; +} + +#endif + template inline bool operator<(shared_ptr const & a, shared_ptr const & b) BOOST_NOEXCEPT { return a.owner_before( b ); diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 2c95dd9..9f08375 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -75,6 +75,8 @@ import testing ; [ run sp_convertible_test.cpp ] [ run sp_array_n_test.cpp ] [ run sp_array_cast_test.cpp ] + [ run sp_zero_compare_test.cpp ] + [ run sp_nullptr_test.cpp ] [ compile-fail array_fail_spa_sp_c.cpp ] [ compile-fail array_fail_sp_spa_c.cpp ] diff --git a/test/sp_nullptr_test.cpp b/test/sp_nullptr_test.cpp new file mode 100644 index 0000000..a1779bb --- /dev/null +++ b/test/sp_nullptr_test.cpp @@ -0,0 +1,140 @@ +// +// sp_nullptr_test.cpp +// +// Copyright 2012 Peter Dimov +// +// Distributed under 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) +// + +#include +#include +#include +#include + +#if !defined( BOOST_NO_CXX11_NULLPTR ) + +struct X +{ + static int instances; + + X() + { + ++instances; + } + + ~X() + { + --instances; + } + +private: + + X( X const & ); + X & operator=( X const & ); +}; + +int X::instances = 0; + +void f( std::nullptr_t ) +{ +} + +int main() +{ + { + boost::shared_ptr p( nullptr ); + + BOOST_TEST( p.get() == 0 ); + BOOST_TEST( p.use_count() == 0 ); + + BOOST_TEST( p == nullptr ); + BOOST_TEST( nullptr == p ); + BOOST_TEST( !( p != nullptr ) ); + BOOST_TEST( !( nullptr != p ) ); + } + + { + boost::shared_ptr p( nullptr, f ); + + BOOST_TEST( p.get() == 0 ); + BOOST_TEST( p.use_count() == 1 ); + + BOOST_TEST( p == nullptr ); + BOOST_TEST( nullptr == p ); + BOOST_TEST( !( p != nullptr ) ); + BOOST_TEST( !( nullptr != p ) ); + } + + { + boost::shared_ptr p( nullptr, f, std::allocator() ); + + BOOST_TEST( p.get() == 0 ); + BOOST_TEST( p.use_count() == 1 ); + + BOOST_TEST( p == nullptr ); + BOOST_TEST( nullptr == p ); + BOOST_TEST( !( p != nullptr ) ); + BOOST_TEST( !( nullptr != p ) ); + } + + { + boost::shared_ptr p( new int ); + + BOOST_TEST( p.get() != 0 ); + BOOST_TEST( p.use_count() == 1 ); + + BOOST_TEST( p != nullptr ); + BOOST_TEST( nullptr != p ); + BOOST_TEST( !( p == nullptr ) ); + BOOST_TEST( !( nullptr == p ) ); + + p = nullptr; + + BOOST_TEST( p.get() == 0 ); + BOOST_TEST( p.use_count() == 0 ); + + BOOST_TEST( p == nullptr ); + BOOST_TEST( nullptr == p ); + BOOST_TEST( !( p != nullptr ) ); + BOOST_TEST( !( nullptr != p ) ); + } + + { + BOOST_TEST( X::instances == 0 ); + + boost::shared_ptr p( new X ); + BOOST_TEST( X::instances == 1 ); + + BOOST_TEST( p.get() != 0 ); + BOOST_TEST( p.use_count() == 1 ); + + BOOST_TEST( p != nullptr ); + BOOST_TEST( nullptr != p ); + BOOST_TEST( !( p == nullptr ) ); + BOOST_TEST( !( nullptr == p ) ); + + p = nullptr; + BOOST_TEST( X::instances == 0 ); + + BOOST_TEST( p.get() == 0 ); + BOOST_TEST( p.use_count() == 0 ); + + BOOST_TEST( p == nullptr ); + BOOST_TEST( nullptr == p ); + BOOST_TEST( !( p != nullptr ) ); + BOOST_TEST( !( nullptr != p ) ); + } + + return boost::report_errors(); +} + +#else + +int main() +{ + return 0; +} + +#endif diff --git a/test/sp_zero_compare_test.cpp b/test/sp_zero_compare_test.cpp new file mode 100644 index 0000000..e326d34 --- /dev/null +++ b/test/sp_zero_compare_test.cpp @@ -0,0 +1,78 @@ +// +// sp_zero_compare_test.cpp - == 0, != 0 +// +// Copyright 2012 Peter Dimov +// +// Distributed under 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) +// + +#include +#include +#include +#include +#include +#include + +struct W +{ +}; + +void intrusive_ptr_add_ref( W* ) +{ +} + +void intrusive_ptr_release( W* ) +{ +} + +int main() +{ + { + boost::scoped_ptr p; + + BOOST_TEST( p == 0 ); + BOOST_TEST( 0 == p ); + BOOST_TEST( !( p != 0 ) ); + BOOST_TEST( !( 0 != p ) ); + } + + { + boost::scoped_array p; + + BOOST_TEST( p == 0 ); + BOOST_TEST( 0 == p ); + BOOST_TEST( !( p != 0 ) ); + BOOST_TEST( !( 0 != p ) ); + } + + { + boost::shared_ptr p; + + BOOST_TEST( p == 0 ); + BOOST_TEST( 0 == p ); + BOOST_TEST( !( p != 0 ) ); + BOOST_TEST( !( 0 != p ) ); + } + + { + boost::shared_array p; + + BOOST_TEST( p == 0 ); + BOOST_TEST( 0 == p ); + BOOST_TEST( !( p != 0 ) ); + BOOST_TEST( !( 0 != p ) ); + } + + { + boost::intrusive_ptr p; + + BOOST_TEST( p == 0 ); + BOOST_TEST( 0 == p ); + BOOST_TEST( !( p != 0 ) ); + BOOST_TEST( !( 0 != p ) ); + } + + return boost::report_errors(); +}