Index: boost/unique_ptr.hpp =================================================================== --- boost/unique_ptr.hpp (revision 0) +++ boost/unique_ptr.hpp (revision 0) @@ -0,0 +1,377 @@ +/////////////////////////////////////////////////////////////////////////////// +// unique_ptr.hpp header file +// +// Copyright 2009 Howard Hinnant. +// 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) +// See http://www.boost.org/libs/foreach for documentation + +// This is a C++03 emulation of std::unique_ptr placed in namespace boost. +// Reference http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2800.pdf +// for the latest unique_ptr specification, and +// reference http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html +// for any pending issues against this specification. + +#ifndef BOOST_UNIQUE_PTR_HPP +#define BOOST_UNIQUE_PTR_HPP + +#include +#include +#include +#include +#include + +namespace boost +{ + +// A fake, do-nothing move to handle move-ignorant types. +// Remove if you've got another definition to handle this. +template +inline +T& +move(T& t) +{ + return t; +} + +template +struct default_delete +{ + default_delete() {} + template + default_delete(const default_delete&, + typename enable_if_c::value>::type* = 0) + {} + + void operator()(T* ptr) const + { + BOOST_STATIC_ASSERT(sizeof(T) > 0); + delete ptr; + } +}; + +template +struct default_delete +{ + void operator()(T* ptr) const + { + BOOST_STATIC_ASSERT(sizeof(T) > 0); + delete [] ptr; + } + +private: + + template void operator()(U*) const; +}; + +namespace detail +{ + +typedef char one; +struct two {one _[2];}; + +namespace pointer_type_imp +{ + +template static two test(...); +template static one test(typename U::pointer* = 0); + +} // pointer_type_imp + +template +struct has_pointer_type +{ + static const bool value = sizeof(pointer_type_imp::test(0)) == 1; +}; + +namespace pointer_type_imp +{ + +template ::value> +struct pointer_type +{ + typedef typename D::pointer type; +}; + +template +struct pointer_type +{ + typedef T* type; +}; + +} // pointer_type_imp + +template +struct pointer_type +{ + typedef typename pointer_type_imp::pointer_type::type>::type type; +}; + +} // detail + +template > +class unique_ptr +{ +public: + typedef T element_type; + typedef D deleter_type; + typedef typename detail::pointer_type::type pointer; + +private: + boost::compressed_pair ptr_; + + typedef typename add_reference::type deleter_reference; + typedef typename add_reference::type deleter_const_reference; + + struct nat {int for_bool_;}; + + unique_ptr(unique_ptr&); + unique_ptr& operator=(unique_ptr&); + + class rv + { + unique_ptr& r_; + public: + explicit rv(unique_ptr& r) : r_(r) {} + unique_ptr* operator->() {return &r_;} + }; + +public: + operator rv() {return rv(*this);} + unique_ptr(rv r) : ptr_(r->release(), move(r->get_deleter())) {} + unique_ptr& operator=(rv r) + { + reset(r->release()); + ptr_.second() = move(r->get_deleter()); + return *this; + } + friend unique_ptr move(unique_ptr& u) {return unique_ptr(rv(u));} + friend unique_ptr move(rv r) {return unique_ptr(r);} + + unique_ptr() + : ptr_(pointer(), deleter_type()) + { + BOOST_STATIC_ASSERT(!is_pointer::value); + } + + explicit unique_ptr(pointer p) + : ptr_(p, deleter_type()) + { + BOOST_STATIC_ASSERT(!is_pointer::value); + } + + unique_ptr(pointer p, typename mpl::if_< + is_reference, + D, + typename add_reference::type>::type d) + : ptr_(p, d) {} + + template + unique_ptr(unique_ptr u, + typename enable_if_c + < + is_convertible::pointer, pointer>::value && + is_convertible::value && + ( + !is_reference::value || + is_same::value + ) + >::type* = 0) + : ptr_(u.release(), u.get_deleter()) {} + + ~unique_ptr() {reset();} + + unique_ptr& operator=(int nat::*) + { + reset(); + return *this; + } + + template + unique_ptr& + operator=(unique_ptr u) + { + reset(u.release()); + ptr_.second() = move(u.get_deleter()); + return *this; + } + + typename add_reference::type operator*() const {return *get();} + pointer operator->() const {return get();} + pointer get() const {return ptr_.first();} + deleter_reference get_deleter() {return ptr_.second();} + deleter_const_reference get_deleter() const {return ptr_.second();} + operator int nat::*() const {return get() ? &nat::for_bool_ : 0;} + + void reset(pointer p = pointer()) + { + pointer t = get(); + if (t != pointer()) + get_deleter()(t); + ptr_.first() = p; + } + + pointer release() + { + pointer tmp = get(); + ptr_.first() = pointer(); + return tmp; + } + + void swap(unique_ptr& u) {ptr_.swap(u.ptr_);} +}; + +template +class unique_ptr +{ +public: + typedef T element_type; + typedef D deleter_type; + typedef typename detail::pointer_type::type pointer; + +private: + boost::compressed_pair ptr_; + + typedef typename add_reference::type deleter_reference; + typedef typename add_reference::type deleter_const_reference; + + struct nat {int for_bool_;}; + + unique_ptr(unique_ptr&); + unique_ptr& operator=(unique_ptr&); + + class rv + { + unique_ptr& r_; + public: + explicit rv(unique_ptr& r) : r_(r) {} + unique_ptr* operator->() {return &r_;} + }; + +public: + operator rv() {return rv(*this);} + unique_ptr(rv r) : ptr_(r->release(), move(r->get_deleter())) {} + unique_ptr& operator=(rv r) + { + reset(r->release()); + ptr_.second() = move(r->get_deleter()); + return *this; + } + friend unique_ptr move(unique_ptr& u) {return unique_ptr(rv(u));} + friend unique_ptr move(rv r) {return unique_ptr(r);} + + unique_ptr() + : ptr_(pointer(), deleter_type()) + { + BOOST_STATIC_ASSERT(!is_pointer::value); + } + + explicit unique_ptr(pointer p) + : ptr_(p, deleter_type()) + { + BOOST_STATIC_ASSERT(!is_pointer::value); + } + + unique_ptr(pointer p, typename mpl::if_< + is_reference, + D, + typename add_reference::type>::type d) + : ptr_(p, d) {} + + ~unique_ptr() {reset();} + + unique_ptr& operator=(int nat::*) + { + reset(); + return *this; + } + + T& operator[](size_t i) const {return get()[i];} + pointer get() const {return ptr_.first();} + deleter_reference get_deleter() {return ptr_.second();} + deleter_const_reference get_deleter() const {return ptr_.second();} + operator int nat::*() const {return get() ? &nat::for_bool_ : 0;} + + void reset(pointer p = pointer()) + { + pointer t = get(); + if (t != pointer()) + get_deleter()(t); + ptr_.first() = p; + } + + pointer release() + { + pointer tmp = get(); + ptr_.first() = pointer(); + return tmp; + } + + void swap(unique_ptr& u) {ptr_.swap(u.ptr_);} +private: + template + explicit unique_ptr(U, + typename enable_if_c::value>::type* = 0); +}; + +template +inline +void +swap(unique_ptr& x, unique_ptr& y) +{ + x.swap(y); +} + +template +inline +bool +operator==(const unique_ptr& x, const unique_ptr& y) +{ + return x.get() == y.get(); +} + +template +inline +bool +operator!=(const unique_ptr& x, const unique_ptr& y) +{ + return !(x == y); +} + +template +inline +bool +operator<(const unique_ptr& x, const unique_ptr& y) +{ + return x.get() < y.get(); +} + +template +inline +bool +operator<=(const unique_ptr& x, const unique_ptr& y) +{ + return !(y < x); +} + +template +inline +bool +operator>(const unique_ptr& x, const unique_ptr& y) +{ + return y < x; +} + +template +inline +bool +operator>=(const unique_ptr& x, const unique_ptr& y) +{ + return !(x < y); +} + +} // boost + +#endif // UNIQUE_PTR_HPP Index: libs/smart_ptr/test/unique_ptr_nonmove_named.cpp =================================================================== --- libs/smart_ptr/test/unique_ptr_nonmove_named.cpp (revision 0) +++ libs/smart_ptr/test/unique_ptr_nonmove_named.cpp (revision 0) @@ -0,0 +1,31 @@ +// +// unique_ptr_nonmove_named.cpp - a negative test for moving from named objects +// +// Copyright 2008 Howard Hinnant +// +// 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 + +boost::unique_ptr factory(int i) +{ + return boost::unique_ptr(new int(i)); +} + +void client(boost::unique_ptr p) +{ + // Ownership transferred into client +} // int deleted here + +int main() +{ + boost::unique_ptr p = factory(2); + // *p == 2 + p.reset(new int(3)); + // *p == 3 + // error: unique_ptr::unique_ptr(unique_ptr&) is private + client(p); +} Index: libs/smart_ptr/test/unique_ptr_malloc_free.cpp =================================================================== --- libs/smart_ptr/test/unique_ptr_malloc_free.cpp (revision 0) +++ libs/smart_ptr/test/unique_ptr_malloc_free.cpp (revision 0) @@ -0,0 +1,19 @@ +// +// unique_ptr_malloc_free.cpp - a positive test for using malloc & free +// +// Copyright 2008 Howard Hinnant +// +// 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 + +int main() +{ + boost::unique_ptr p( + (int*)std::malloc(sizeof(int)), std::free); + *p = 1; +} // free(p.get()) Index: libs/smart_ptr/test/Jamfile.v2 =================================================================== --- libs/smart_ptr/test/Jamfile.v2 (revision 50450) +++ libs/smart_ptr/test/Jamfile.v2 (working copy) @@ -50,5 +50,9 @@ [ run wp_convertible_test.cpp ] [ run ip_convertible_test.cpp ] [ run allocate_shared_test.cpp ] + [ run unique_ptr_move_temps.cpp ] + [ compile-fail unique_ptr_nonmove_named.cpp ] + [ run unique_ptr_move_named.cpp ] + [ run unique_ptr_malloc_free.cpp ] ; } Index: libs/smart_ptr/test/unique_ptr_move_named.cpp =================================================================== --- libs/smart_ptr/test/unique_ptr_move_named.cpp (revision 0) +++ libs/smart_ptr/test/unique_ptr_move_named.cpp (revision 0) @@ -0,0 +1,32 @@ +// +// unique_ptr_move_named.cpp - a positive test for explicitly moving from +// named objects +// +// Copyright 2008 Howard Hinnant +// +// 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 + +boost::unique_ptr factory(int i) +{ + return boost::unique_ptr(new int(i)); +} + +void client(boost::unique_ptr p) +{ + // Ownership transferred into client +} // int deleted here + +int main() +{ + boost::unique_ptr p = factory(2); + // *p == 2 + p.reset(new int(3)); + // *p == 3 + client(move(p)); // ok now + // p is "null" here +} Index: libs/smart_ptr/test/unique_ptr_move_temps.cpp =================================================================== --- libs/smart_ptr/test/unique_ptr_move_temps.cpp (revision 0) +++ libs/smart_ptr/test/unique_ptr_move_temps.cpp (revision 0) @@ -0,0 +1,30 @@ +// +// unique_ptr_move_temps.cpp - a positive test for moving from temporaries +// +// Copyright 2008 Howard Hinnant +// +// 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 + +boost::unique_ptr factory(int i) +{ + return boost::unique_ptr(new int(i)); +} + +void client(boost::unique_ptr p) +{ + // Ownership transferred into client +} // int deleted here + +int main() +{ + boost::unique_ptr p = factory(2); + // *p == 2 + p.reset(new int(3)); + // *p == 3 + client(factory(4)); +}