Boost logo

Boost :

Subject: Re: [boost] C++03 unique_ptr emulation
From: Howard Hinnant (hinnant_at_[hidden])
Date: 2009-01-07 20:40:13


On Jan 3, 2009, at 6:41 PM, Howard Hinnant wrote:

> On Jan 3, 2009, at 4:45 PM, Sebastian Redl wrote:
>
>> Howard Hinnant wrote:
>>> On Jan 3, 2009, at 3:45 PM, Sebastian Redl wrote:
>>>
>>>>
>>>> Anyway, I'll try to boostify your project and post back.
>>>
>>> That is very kind of you.
>> I did something somewhat simpler. Attached is a patch against Boost
>> trunk that makes unique_ptr a part of the smart_ptr library, as far
>> as
>> the header and the tests are concerned. (Those are some of the
>> examples,
>> not the tests you just uploaded.) The patch does not modify
>> smart_ptr.hpp, though.
>> The tests are now executed as part of the normal test suite, and they
>> all pass. They are somewhat incomplete, though.
>
> Thanks Sebastian. I'll continue to make incremental improvements to http://home.roadrunner.com/~hinnant/unique_ptr03.html
> , and hopefully the goal of simply exposing more C++ programmers to
> a preview of std::unique_ptr will be realized.

I've uploaded what is I think a fairly complete unique_ptr.hpp and
testsuite to:

    http://home.roadrunner.com/~hinnant/unique_ptr03.html

If you download the zip, you get the header + testsuite. The
testsuite is hierarchical, organized according to N2800's
[unique.ptr]. One can:

$ export CC=g++
$ export BOOST_INCLUDE="-I/<path-to>/boost-trunk"
$ export SOURCE_INCLUDE="-I/<path-to-unique_ptr.hpp>"

And then cd into any directory under unique.ptr and:

$ ./test

(assumes bash-compatible environment)

This allows you to test as little or as much of the unique_ptr
testsuite as you want, by cd'ing up or down and just testing what is
under your pwd.

I haven't put it into a boost sandbox. I have no objection if someone
does (and adds-to/modifies it). I've included Ion on the copyright
list as I felt I used some of his code. If you're not comfortable
with that Ion, just let me know. If I've missed someone who should be
on there, please let me know. I've done a poor job of keeping track
of who's contributed what and would like to give credit where credit
is due.

If you want to add to the testsuite it is pretty self-explanatory.
Just create a test and have the name end with ".pass.cpp" if the test
is supposed to pass (return 0 on success). If the test is supposed to
fail at compile time, name it ending with ".fail.cpp".

Noteworthy points:

* 3 of the tests currently fail for me (fail at compile time,
supposed to compile, run and pass). These are all associated with the
converting constructor specified in [unique.ptr.single.ctor]. When
the source and target are of different type, this emulation demands
that the conversion be explicit, and refuses to compile on implicit
conversions:

unique_ptr<base> b(unique_ptr<derived>()); // ok

unique_ptr<base> b = unique_ptr<derived>(); // causes 3 compile time
failures under unique.ptr/unique.ptr.single/unique.ptr.single.ctor

I consider this not bad for an emulation. And otherwise things look
pretty good. I was able to get more working than I thought I would.

* I implemented my own boost::detail::is_convertible instead of using
boost::is_convertible. My version does not handle function, array,
void or abstract types, but does handle move-only types (this is all
unique_ptr needs) by considering the From to be an rvalue. The
implementation is a little squirrelly in that it is different
depending upon whether From and To are the same type or not. I
suspect, but do not know for sure, that this is related to CWG issue
291 (http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#291)
which has Dave Abraham's fingerprints on it (fwiw I am in favor of the
resolution of this issue). A version which took into account array,
function, void and abstract types could be built upon this (but
probably wouldn't work for move-only abstract types unless rvalue
references were supported by the compiler).

* I implemented an abbreviated version of boost::compressed_pair
(named detail::unique_ptr_storage) for similar reasons as above: The
boost version lacked support for move-only types and unique_ptr needs
it. I implemented as little as possible to get unique_ptr up and
going. A move-aware compressed_pair (or space-optimizing, move-aware
tuple) would be most interesting, but is not addressed herein.

* There are namespace scope definitions for move and forward. They
aren't perfect, but they aren't too bad. There's no doubt there's
still a little room for improvement on forward (and a unique_ptr test
to detect any such changes).

* The move-only class author must know about boost::detail::rv
(unique_ptr demonstrates use). The move-only class client needs to
know only about boost::move and boost::forward.

* A C++0X version of unique_ptr is not addressed here. Perhaps it
will be in the future, I don't know right now.

* No doubt others (and myself) will find good ways to improve both
the implementation and testsuite. But this is the first version I'm
willing to call fairly complete. I believe there are 151 tests: 63
that are supposed to pass and 88 that are supposed to fail.

* This was all tested on g++ 4.0. I have no idea what it will take
to get it working on other compilers. To the best of my knowledge, it
should work on any conforming C++03 compiler.

* This exercise generated one LWG issue against unique_ptr (which I
haven't yet posted). As currently specified a unique_ptr<A[],
Deleter> may convert to a unique_ptr<A, Deleter>. This implementation
and testsuite has a test demanding this not happen, and I will get an
LWG posted to this effect.

-Howard


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk