|
Boost : |
Subject: [boost] [move][unique_ptr] c++14 unique_ptr comes to town
From: Ion Gaztañaga (igaztanaga_at_[hidden])
Date: 2014-08-22 13:42:24
Hi to all,
We've discussed about a boostified version of std::unique_ptr several
times in later years. I decided we could not continue with this hole in
the Boost toolset and implemented in Boost.Move a unique_ptr that
follows the C++14 interface. Commit here:
SHA-1: e1da7c5ca1162841f643331af891a9a730eba118
http://github.com/boostorg/move/commit/e1da7c5ca1162841f643331af891a9a730eba118
This implementation is also usable from C++03, and apart from the
general limitations of the Boost.Move machinery, it should be really
uesful for C++03 users. I would like to make this implementation the
official boost::unique_ptr implementation, but until the community
approves this, it's in boost::movelib namespace (boost::move it's a
function so I needed to tweak the namespace name).
I would like to thank Howard Hinnant for his great public implementation
of the emulated unique_ptr published here:
http://home.roadrunner.com/~hinnant/unique_ptr03.html
I've ported and refactored Howard's extensive testsuite to implement
boost test cases. Really useful to detect many implementation errors and
details.
I've found unique_ptr much harder to write than I expected. The standard
text is really detailed and helps implementors, but things like allowed
conversion between pointers and deleters and several ICEs and different
SFINAE parties on many compilers made the work quite entertaining.
The API is taken from the draft n3797 and the implementation has some
differences with the standard. The main reason for this is that I wanted
to make unique_ptr as lightweight as possible avoiding external
dependencies, as it's interesting to implement idioms like PIMPL.
Main attributes and differences with the standard:
-> Implemented in two headers: <boost/move/unique_ptr.hpp> and
<boost/move/make unique.hpp>.
-> <boost/move/unique_ptr.hpp>: Boost.Move is the only heavyweight
dependency. Not even that, as unique_ptr.hpp only uses
boost/move/utility_core.hpp, that does not depend on any external
library excepct BoostConfig and StaticAssert. No TypeTraits, MPL and
others. Only Boost.Config, BOOST_STATIC_ASSERT and BOOST_ASSERT are used
in the implementation. No standard library headers used (no
pointer_traits, memory or other utilities).
-> <boost/move/make unique.hpp>: Boost.PP is used in compilers without
variadic templates. This is the main reason to have a separate
make_unique.hpp header and avoid pulling Boost.PP for c++03 users that
only want to have C++11 unique_ptr.
-> unique_ptr's "operator <" is implemented as x.get() < y.get() instead
of std::less<CT>(). std::less requires <funcional>. std::common_type
requires C++11 standard library or some partial emulation based on
Boost.TypeOf. I don't think 99,99% of users will notice the difference.
For raw pointers, in all our platforms comparisons provide strict weak
ordering. If a smart pointer writer specializes std::less for its smart
pointer, it should be a law against that.
-> It's assignable from literal 0. I found some problems in some
compilers trying to write a constructor for that.
-> nullptr support is conditional on !defined(BOOST_NO_CXX11_NULLPTR)
but I think really should have a Boost nullptr for C++03 compilers.
Let's put Meyer's nullptr
(http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/nullptr) in Boost for
BOOST_NO_CXX11_NULLPTR compilers.
-> unique_ptr<T[]> is convertible to other types when conversion is
considered safe. This means that unique_ptr<T[]> is convertible to
unique_ptr<const volatile T[]>. Conversion from T[] to U[] is considered
safe if remove_cv<T> is the same type as remove_cv<U> and
unique_ptr<T[]>::pointer is convertible to unique_ptr<U[]>::pointer.
This is a feature that might go to C++17
(http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#2118). Safe
conversions in reset() and constructors from pointers are also
implemented in unique_ptr<T[]>.
I tested the implementation in GCC{4.4, 4.6, 4.7, 4.8} Clang3.4 and
MSVC{7.1, 8.0, 9.0, 10.0, 11.0, 12.0} in 32/64 bits, debug/release and
C++03/C++11 modes (where applicable).
The class documentation is generated with Boost.Move documentation and
the most part of it is taken from the standard. I haven't added a
tutorial to Boost.Move but I plan to it based on Howard's c++03
unique_ptr tutorial.
I hope you find this addition to Boost.Move useful. If you think the
implementation is good enough to be the official boost::unique_ptr
implementation living in Boost.SmartPtr, porting should be easy, except
for the documentation part. That would require either combining somehow
handwritten and Quickbook produced documentation or writing new docs for
unique_ptr.
Best,
Ion
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk