diff mbox

[1/2] add unique_ptr header

Message ID 20170731234607.21952-2-tbsaunde+gcc@tbsaunde.org
State New
Headers show

Commit Message

tbsaunde+gcc@tbsaunde.org July 31, 2017, 11:46 p.m. UTC
From: Trevor Saunders <tbsaunde+gcc@tbsaunde.org>

For most of the history of this see 
https://sourceware.org/ml/gdb-patches/2016-10/msg00223.html
The changes are mostly s/gdb/gtl/g

include/ChangeLog:

2017-07-29  Trevor Saunders  <tbsaunde+gcc@tbsaunde.org>

	* unique-ptr.h: New file.
---
 include/unique-ptr.h | 386 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 386 insertions(+)
 create mode 100644 include/unique-ptr.h

Comments

David Malcolm Aug. 1, 2017, 2:40 p.m. UTC | #1
On Mon, 2017-07-31 at 19:46 -0400, tbsaunde+gcc@tbsaunde.org wrote:
> From: Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
> 
> For most of the history of this see 
> https://sourceware.org/ml/gdb-patches/2016-10/msg00223.html
> The changes are mostly s/gdb/gtl/g
> 
> include/ChangeLog:
> 
> 2017-07-29  Trevor Saunders  <tbsaunde+gcc@tbsaunde.org>
> 
> 	* unique-ptr.h: New file.
> ---
>  include/unique-ptr.h | 386
> +++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 386 insertions(+)
>  create mode 100644 include/unique-ptr.h
> 
> diff --git a/include/unique-ptr.h b/include/unique-ptr.h
> new file mode 100644
> index 00000000000..7903a5abefe
> --- /dev/null
> +++ b/include/unique-ptr.h
> @@ -0,0 +1,386 @@
> +/* gtl::unique_ptr, a simple std::unique_ptr replacement for C++03.
> +
> +   Copyright (C) 2007-2016 Free Software Foundation, Inc.
> +
> +   This file is part of GCC.
> +
> +   This program is free software; you can redistribute it and/or
> modify
> +   it under the terms of the GNU General Public License as published
> by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/license
> s/>.  */
> +
> +/* gtl::unique_ptr defines a C++ owning smart pointer that exposes a
> +   subset of the std::unique_ptr API.
> +
> +   In fact, when compiled with a C++11 compiler, gtl::unique_ptr
> +   actually _is_ std::unique_ptr.  When compiled with a C++03
> compiler
> +   OTOH, it's an hand coded std::unique_ptr emulation that assumes
> +   code is correct and doesn't try to be too smart.

The comments talk about C++03 (presumably due to the gdb heritage of
this code), but gcc's minimum requirement is for C++98.

Does this code work with C++98?  If so, presumably this comment should
state that (presumably by just writing "C++98 or C++03" wherever you
say "C++03").

[...snip...]

Could the patch add a set of selftests for the new code?  (e.g. assert
the number of times that a destructor is called, for various test
classes in various situations).  This would also give a handy way to
run the pertinent code relatively quickly under valgrind (via "make
selftest-valgrind").

I'm not a global reviewer, so treat these as suggestions.

Hope this is helpful
Dave
Trevor Saunders Aug. 2, 2017, 3:09 a.m. UTC | #2
On Tue, Aug 01, 2017 at 10:40:53AM -0400, David Malcolm wrote:
> On Mon, 2017-07-31 at 19:46 -0400, tbsaunde+gcc@tbsaunde.org wrote:
> > From: Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
> > 
> > For most of the history of this see 
> > https://sourceware.org/ml/gdb-patches/2016-10/msg00223.html
> > The changes are mostly s/gdb/gtl/g
> > 
> > include/ChangeLog:
> > 
> > 2017-07-29  Trevor Saunders  <tbsaunde+gcc@tbsaunde.org>
> > 
> > 	* unique-ptr.h: New file.
> > ---
> >  include/unique-ptr.h | 386
> > +++++++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 386 insertions(+)
> >  create mode 100644 include/unique-ptr.h
> > 
> > diff --git a/include/unique-ptr.h b/include/unique-ptr.h
> > new file mode 100644
> > index 00000000000..7903a5abefe
> > --- /dev/null
> > +++ b/include/unique-ptr.h
> > @@ -0,0 +1,386 @@
> > +/* gtl::unique_ptr, a simple std::unique_ptr replacement for C++03.
> > +
> > +   Copyright (C) 2007-2016 Free Software Foundation, Inc.
> > +
> > +   This file is part of GCC.
> > +
> > +   This program is free software; you can redistribute it and/or
> > modify
> > +   it under the terms of the GNU General Public License as published
> > by
> > +   the Free Software Foundation; either version 3 of the License, or
> > +   (at your option) any later version.
> > +
> > +   This program is distributed in the hope that it will be useful,
> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > +   GNU General Public License for more details.
> > +
> > +   You should have received a copy of the GNU General Public License
> > +   along with this program.  If not, see <http://www.gnu.org/license
> > s/>.  */
> > +
> > +/* gtl::unique_ptr defines a C++ owning smart pointer that exposes a
> > +   subset of the std::unique_ptr API.
> > +
> > +   In fact, when compiled with a C++11 compiler, gtl::unique_ptr
> > +   actually _is_ std::unique_ptr.  When compiled with a C++03
> > compiler
> > +   OTOH, it's an hand coded std::unique_ptr emulation that assumes
> > +   code is correct and doesn't try to be too smart.
> 
> The comments talk about C++03 (presumably due to the gdb heritage of
> this code), but gcc's minimum requirement is for C++98.
> 
> Does this code work with C++98?  If so, presumably this comment should
> state that (presumably by just writing "C++98 or C++03" wherever you
> say "C++03").

aiui C++03 is C++98 with a few additions to the stl.  Yes this doesn't
build with -std=c++98 I haven't tried any of the strange c++ compilers
out there, but its not very fancy so I expect its fine.

> Could the patch add a set of selftests for the new code?  (e.g. assert
> the number of times that a destructor is called, for various test
> classes in various situations).  This would also give a handy way to
> run the pertinent code relatively quickly under valgrind (via "make
> selftest-valgrind").

Its possible, but I'm not sure it would provide much value.  I think
we're unlikely to change this code much since it already more or less
completely implements the API it is shimming.  It also is fairly
trivial, so I doubt anyone would want to run valgrind on just the
unique_ptr code.  Of course I may just be being lazy here.

thanks

Trev

> 
> I'm not a global reviewer, so treat these as suggestions.
> 
> Hope this is helpful
> Dave
Richard Biener Aug. 2, 2017, 8:14 a.m. UTC | #3
On Tue, Aug 1, 2017 at 4:40 PM, David Malcolm <dmalcolm@redhat.com> wrote
> On Mon, 2017-07-31 at 19:46 -0400, tbsaunde+gcc@tbsaunde.org wrote:
>> From: Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
>>
>> For most of the history of this see
>> https://sourceware.org/ml/gdb-patches/2016-10/msg00223.html
>> The changes are mostly s/gdb/gtl/g
>>
>> include/ChangeLog:
>>
>> 2017-07-29  Trevor Saunders  <tbsaunde+gcc@tbsaunde.org>
>>
>>       * unique-ptr.h: New file.
>> ---
>>  include/unique-ptr.h | 386
>> +++++++++++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 386 insertions(+)
>>  create mode 100644 include/unique-ptr.h
>>
>> diff --git a/include/unique-ptr.h b/include/unique-ptr.h
>> new file mode 100644
>> index 00000000000..7903a5abefe
>> --- /dev/null
>> +++ b/include/unique-ptr.h
>> @@ -0,0 +1,386 @@
>> +/* gtl::unique_ptr, a simple std::unique_ptr replacement for C++03.
>> +
>> +   Copyright (C) 2007-2016 Free Software Foundation, Inc.
>> +
>> +   This file is part of GCC.
>> +
>> +   This program is free software; you can redistribute it and/or
>> modify
>> +   it under the terms of the GNU General Public License as published
>> by
>> +   the Free Software Foundation; either version 3 of the License, or
>> +   (at your option) any later version.
>> +
>> +   This program is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> +   GNU General Public License for more details.
>> +
>> +   You should have received a copy of the GNU General Public License
>> +   along with this program.  If not, see <http://www.gnu.org/license
>> s/>.  */
>> +
>> +/* gtl::unique_ptr defines a C++ owning smart pointer that exposes a
>> +   subset of the std::unique_ptr API.
>> +
>> +   In fact, when compiled with a C++11 compiler, gtl::unique_ptr
>> +   actually _is_ std::unique_ptr.  When compiled with a C++03
>> compiler
>> +   OTOH, it's an hand coded std::unique_ptr emulation that assumes
>> +   code is correct and doesn't try to be too smart.
>
> The comments talk about C++03 (presumably due to the gdb heritage of
> this code), but gcc's minimum requirement is for C++98.

It's actually C++04 but I don't remember the details.  It happens to work
with GCC 3.4 and thus C++98 though.

Richard.

> Does this code work with C++98?  If so, presumably this comment should
> state that (presumably by just writing "C++98 or C++03" wherever you
> say "C++03").
>
> [...snip...]
>
> Could the patch add a set of selftests for the new code?  (e.g. assert
> the number of times that a destructor is called, for various test
> classes in various situations).  This would also give a handy way to
> run the pertinent code relatively quickly under valgrind (via "make
> selftest-valgrind").
>
> I'm not a global reviewer, so treat these as suggestions.
>
> Hope this is helpful
> Dave
Jonathan Wakely Aug. 4, 2017, 7:55 p.m. UTC | #4
On 01/08/17 23:09 -0400, Trevor Saunders wrote:
>aiui C++03 is C++98 with a few additions to the stl.

Again, STL != C++ Standard Library.

C++03 made some important changes to the core language, particularly
the value-initialization rules.

Most of the library changes were small bug fixes, and most were to
locales (which didn't originate in the STL and aren't even templates)
and iostreams (which didn't originate in the STL).

There were also changes to std::auto_ptr (also not from the STL) which
this might rely on (I haven't checked).
Trevor Saunders Aug. 5, 2017, 5:39 a.m. UTC | #5
On Fri, Aug 04, 2017 at 08:55:50PM +0100, Jonathan Wakely wrote:
> On 01/08/17 23:09 -0400, Trevor Saunders wrote:
> > aiui C++03 is C++98 with a few additions to the stl.
> 
> Again, STL != C++ Standard Library.
> 
> C++03 made some important changes to the core language, particularly
> the value-initialization rules.
> 
> Most of the library changes were small bug fixes, and most were to
> locales (which didn't originate in the STL and aren't even templates)
> and iostreams (which didn't originate in the STL).
> 
> There were also changes to std::auto_ptr (also not from the STL) which
> this might rely on (I haven't checked).

I doubt it, as Pedro said in his email it originally copied code from
std::auto_ptr, but it doesn't use the standard libraries definition of
std::auto_ptr anywhere.  However please do feel free to look at the
implementation.

Trev

> 
>
David Malcolm Oct. 11, 2017, 6:16 p.m. UTC | #6
On Sat, 2017-08-05 at 01:39 -0400, Trevor Saunders wrote:
> On Fri, Aug 04, 2017 at 08:55:50PM +0100, Jonathan Wakely wrote:
> > On 01/08/17 23:09 -0400, Trevor Saunders wrote:
> > > aiui C++03 is C++98 with a few additions to the stl.
> > 
> > Again, STL != C++ Standard Library.
> > 
> > C++03 made some important changes to the core language,
> > particularly
> > the value-initialization rules.
> > 
> > Most of the library changes were small bug fixes, and most were to
> > locales (which didn't originate in the STL and aren't even
> > templates)
> > and iostreams (which didn't originate in the STL).
> > 
> > There were also changes to std::auto_ptr (also not from the STL)
> > which
> > this might rely on (I haven't checked).
> 
> I doubt it, as Pedro said in his email it originally copied code from
> std::auto_ptr, but it doesn't use the standard libraries definition
> of
> std::auto_ptr anywhere.  However please do feel free to look at the
> implementation.
> 
> Trev
> 

Trevor: did this go anywhere?

Do we have an unique_ptr class we can use within gcc's own
implementation?

(I was hoping to use it for
  https://gcc.gnu.org/ml/gcc-patches/2017-05/msg00439.html
  "[PATCH 1/3] c-family: add name_hint/deferred_diagnostic";
see the discussion at:
  https://gcc.gnu.org/ml/gcc-patches/2017-07/msg00123.html
onwards)

Thanks
Dave
Trevor Saunders Oct. 12, 2017, 2:02 p.m. UTC | #7
On Wed, Oct 11, 2017 at 02:16:38PM -0400, David Malcolm wrote:
> On Sat, 2017-08-05 at 01:39 -0400, Trevor Saunders wrote:
> > On Fri, Aug 04, 2017 at 08:55:50PM +0100, Jonathan Wakely wrote:
> > > On 01/08/17 23:09 -0400, Trevor Saunders wrote:
> > > > aiui C++03 is C++98 with a few additions to the stl.
> > > 
> > > Again, STL != C++ Standard Library.
> > > 
> > > C++03 made some important changes to the core language,
> > > particularly
> > > the value-initialization rules.
> > > 
> > > Most of the library changes were small bug fixes, and most were to
> > > locales (which didn't originate in the STL and aren't even
> > > templates)
> > > and iostreams (which didn't originate in the STL).
> > > 
> > > There were also changes to std::auto_ptr (also not from the STL)
> > > which
> > > this might rely on (I haven't checked).
> > 
> > I doubt it, as Pedro said in his email it originally copied code from
> > std::auto_ptr, but it doesn't use the standard libraries definition
> > of
> > std::auto_ptr anywhere.  However please do feel free to look at the
> > implementation.
> > 
> > Trev
> > 
> 
> Trevor: did this go anywhere?

I'm sorry, I've been pretty busy starting a new job, and haven't yet
finished the paperwork to get permission to work on gcc stuff.  So I
haven't done anything since my last message in the thread.

> Do we have an unique_ptr class we can use within gcc's own
> implementation?

Not yet :(

> (I was hoping to use it for
>   https://gcc.gnu.org/ml/gcc-patches/2017-05/msg00439.html
>   "[PATCH 1/3] c-family: add name_hint/deferred_diagnostic";
> see the discussion at:
>   https://gcc.gnu.org/ml/gcc-patches/2017-07/msg00123.html
> onwards)

I believe you should be good to take the last version of the patch I
submitted and sed the namespace name to whatever people can agree on.  I
think that was the only issue people had with the patch.  I'd really
like to see this get into gcc8, and will try to get stuff done on my
end, but I'd also be thankful if you felt like doing that work first.

Trev

> 
> Thanks
> Dave
diff mbox

Patch

diff --git a/include/unique-ptr.h b/include/unique-ptr.h
new file mode 100644
index 00000000000..7903a5abefe
--- /dev/null
+++ b/include/unique-ptr.h
@@ -0,0 +1,386 @@ 
+/* gtl::unique_ptr, a simple std::unique_ptr replacement for C++03.
+
+   Copyright (C) 2007-2016 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* gtl::unique_ptr defines a C++ owning smart pointer that exposes a
+   subset of the std::unique_ptr API.
+
+   In fact, when compiled with a C++11 compiler, gtl::unique_ptr
+   actually _is_ std::unique_ptr.  When compiled with a C++03 compiler
+   OTOH, it's an hand coded std::unique_ptr emulation that assumes
+   code is correct and doesn't try to be too smart.
+
+   This supports custom deleters, but not _stateful_ deleters, so you
+   can't use those in C++11 mode either.  Only the managed pointer is
+   stored in the smart pointer.  That could be changed; it simply
+   wasn't found necessary.
+
+   At the end of the file you'll find a gtl::unique_ptr partial
+   specialization that uses a custom (stateless) deleter:
+   gtl::unique_xmalloc_ptr.  That is used to manage pointers to
+   objects allocated with xmalloc.
+
+   The C++03 version was originally based on GCC 7.0's std::auto_ptr
+   and then heavily customized to behave more like C++11's
+   std::unique_ptr, but at this point, it no longer shares much at all
+   with the original file.  But, that's the history and the reason for
+   the copyright's starting year.
+
+   The C++03 version lets you shoot yourself in the foot, since
+   similarly to std::auto_ptr, the copy constructor and assignment
+   operators actually move.  Also, in the name of simplicity, no
+   effort is spent on using SFINAE to prevent invalid conversions,
+   etc.  This is not really a problem, because the goal here is to
+   allow code that would be correct using std::unique_ptr to be
+   equally correct in C++03 mode, and, just as efficient.  If client
+   code compiles correctly with a C++11 (or newer) compiler, we know
+   we're not doing anything invalid by mistake.
+
+   Usage notes:
+
+   - Putting gtl::unique_ptr in standard containers is not supported,
+     since C++03 containers are not move-aware (and our emulation
+     relies on copy actually moving).
+
+   - Since there's no nullptr in C++03, gtl::unique_ptr allows
+     implicit initialization and assignment from NULL instead.
+
+   - To check whether there's an associated managed object, all these
+     work as expected:
+
+      if (ptr)
+      if (!ptr)
+      if (ptr != NULL)
+      if (ptr == NULL)
+      if (NULL != ptr)
+      if (NULL == ptr)
+*/
+
+#ifndef GTL_UNIQUE_PTR_H
+#define GTL_UNIQUE_PTR_H 1
+
+#include <memory>
+
+namespace gtl
+{
+
+#if __cplusplus >= 201103
+
+/* In C++11 mode, all we need is import the standard
+   std::unique_ptr.  */
+template<typename T> using unique_ptr = std::unique_ptr<T>;
+
+/* Pull in move as well.  */
+using std::move;
+
+#else /* C++11 */
+
+/* Default destruction policy used by gtl::unique_ptr when no deleter
+   is specified.  Uses delete.  */
+
+template<typename T>
+struct default_delete
+{
+  void operator () (T *ptr) const { delete ptr; }
+};
+
+/* Specialization for arrays.  Uses delete[].  */
+
+template<typename T>
+struct default_delete<T[]>
+{
+  void operator () (T *ptr) const { delete [] ptr; }
+};
+
+namespace detail
+{
+/* Type used to support implicit construction from NULL:
+
+     gtl::unique_ptr<foo> func (....)
+     {
+     return NULL;
+     }
+
+   and assignment from NULL:
+
+     gtl::unique_ptr<foo> ptr (....);
+     ...
+     ptr = NULL;
+
+  It is intentionally not defined anywhere.  */
+struct nullptr_t;
+
+/* Base class of our unique_ptr emulation.  Contains code common to
+   both unique_ptr<T, D> and unique_ptr<T[], D>.  */
+
+template<typename T, typename D>
+class unique_ptr_base
+{
+public:
+  typedef T *pointer;
+  typedef T element_type;
+  typedef D deleter_type;
+
+  /* Takes ownership of a pointer.  P is a pointer to an object of
+     element_type type.  Defaults to NULL.  */
+  explicit unique_ptr_base (element_type *p = NULL) throw () : m_ptr (p) {}
+
+  /* The "move" constructor.  Really a copy constructor that actually
+     moves.  Even though std::unique_ptr is not copyable, our little
+     simpler emulation allows it, because:
+
+       - There are no rvalue references in C++03.  Our move emulation
+       instead relies on copy/assignment moving, like std::auto_ptr.
+       - RVO/NRVO requires an accessible copy constructor
+  */
+  unique_ptr_base (const unique_ptr_base &other) throw ()
+    : m_ptr (const_cast<unique_ptr_base &> (other).release ()) {}
+
+  /* Converting "move" constructor.  Really an lvalue ref converting
+     constructor that actually moves.  This allows constructs such as:
+
+      unique_ptr<Derived> func_returning_unique_ptr (.....);
+      ...
+      unique_ptr<Base> ptr = func_returning_unique_ptr (.....);
+  */
+  template<typename T1, typename D1>
+  unique_ptr_base (const unique_ptr_base<T1, D1> &other) throw ()
+    : m_ptr (const_cast<unique_ptr_base<T1, D1> &> (other).release ()) {}
+
+  /* The "move" assignment operator.  Really an lvalue ref copy
+     assignment operator that actually moves.  See comments above.  */
+  unique_ptr_base &operator= (const unique_ptr_base &other) throw ()
+  {
+    reset (const_cast<unique_ptr_base &> (other).release ());
+    return *this;
+  }
+
+  /* Converting "move" assignment.  Really an lvalue ref converting
+     copy assignment operator that moves.  See comments above.  */
+  template<typename T1, typename D1>
+  unique_ptr_base &operator= (const unique_ptr_base<T1, D1> &other) throw ()
+  {
+    reset (const_cast<unique_ptr_base<T1, D1> &> (other).release ());
+    return *this;
+  }
+
+  /* std::unique_ptr does not allow assignment, except from nullptr.
+     nullptr doesn't exist in C++03, so we allow assignment from NULL
+     instead [ptr = NULL;].
+  */
+  unique_ptr_base &operator= (detail::nullptr_t *) throw ()
+  {
+    reset ();
+    return *this;
+  }
+
+  ~unique_ptr_base () { call_deleter (); }
+
+  /* "explicit operator bool ()" emulation using the safe bool
+     idiom.  */
+private:
+  typedef void (unique_ptr_base::*explicit_operator_bool) () const;
+  void this_type_does_not_support_comparisons () const {}
+
+public:
+  operator explicit_operator_bool () const
+  {
+    return (m_ptr != NULL
+	    ? &unique_ptr_base::this_type_does_not_support_comparisons
+	    : 0);
+  }
+
+  element_type *get () const throw () { return m_ptr; }
+
+  element_type *release () throw ()
+  {
+    pointer tmp = m_ptr;
+    m_ptr = NULL;
+    return tmp;
+  }
+
+  void reset (element_type *p = NULL) throw ()
+  {
+    if (p != m_ptr)
+      {
+	call_deleter ();
+	m_ptr = p;
+      }
+  }
+
+private:
+
+  /* Call the deleter.  Note we assume the deleter is "stateless".  */
+  void call_deleter ()
+  {
+    D d;
+
+    d (m_ptr);
+  }
+
+  element_type *m_ptr;
+};
+
+} /* namespace detail */
+
+/* Macro used to create a unique_ptr_base "partial specialization" --
+   a subclass that uses a specific deleter.  Basically this re-defines
+   the necessary constructors.  This is necessary because C++03
+   doesn't support inheriting constructors with "using".  While at it,
+   we inherit the assignment operator.  TYPE is the name of the type
+   being defined.  Assumes that 'base_type' is a typedef of the
+   baseclass TYPE is inheriting from.  */
+#define DEFINE_GDB_UNIQUE_PTR(TYPE)						\
+public:									\
+  explicit TYPE (T *p = NULL) throw ()					\
+    : base_type (p) {}							\
+									\
+  TYPE (const TYPE &other) throw () : base_type (other) {}		\
+									\
+  TYPE (detail::nullptr_t *) throw () : base_type (NULL) {}		\
+									\
+  template<typename T1, typename D1>					\
+  TYPE (const detail::unique_ptr_base<T1, D1> &other) throw ()		\
+    : base_type (other) {}						\
+									\
+  using base_type::operator=;
+
+/* Define single-object gtl::unique_ptr.  */
+
+template <typename T, typename D = default_delete<T> >
+class unique_ptr : public detail::unique_ptr_base<T, D>
+{
+  typedef detail::unique_ptr_base<T, D> base_type;
+
+  DEFINE_GDB_UNIQUE_PTR (unique_ptr)
+
+public:
+  /* Dereferencing.  */
+  T &operator* () const throw () { return *this->get (); }
+  T *operator-> () const throw () { return this->get (); }
+};
+
+/* Define gtl::unique_ptr specialization for T[].  */
+
+template <typename T, typename D>
+class unique_ptr<T[], D> : public detail::unique_ptr_base<T, D>
+{
+  typedef detail::unique_ptr_base<T, D> base_type;
+
+  DEFINE_GDB_UNIQUE_PTR (unique_ptr)
+
+public:
+  /* Indexing operator.  */
+  T &operator[] (size_t i) const { return this->get ()[i]; }
+};
+
+/* Comparison operators.  */
+
+template <typename T, typename D,
+	  typename U, typename E>
+inline bool
+operator== (const detail::unique_ptr_base<T, D> &x,
+	    const detail::unique_ptr_base<U, E> &y)
+{ return x.get() == y.get(); }
+
+template <typename T, typename D,
+	  typename U, typename E>
+inline bool
+operator!= (const detail::unique_ptr_base<T, D> &x,
+	    const detail::unique_ptr_base<U, E> &y)
+{ return x.get() != y.get(); }
+
+template<typename T, typename D,
+	 typename U, typename E>
+inline bool
+operator< (const detail::unique_ptr_base<T, D> &x,
+	   const detail::unique_ptr_base<U, E> &y)
+{ return x.get() < y.get (); }
+
+template<typename T, typename D,
+	 typename U, typename E>
+inline bool
+operator<= (const detail::unique_ptr_base<T, D> &x,
+	    const detail::unique_ptr_base<U, E> &y)
+{ return !(y < x); }
+
+template<typename T, typename D,
+	 typename U, typename E>
+inline bool
+operator> (const detail::unique_ptr_base<T, D> &x,
+	   const detail::unique_ptr_base<U, E> &y)
+{ return y < x; }
+
+template<typename T, typename D,
+	 typename U, typename E>
+inline bool
+operator>= (const detail::unique_ptr_base<T, D> &x,
+	    const detail::unique_ptr_base<U, E> &y)
+{ return !(x < y); }
+
+/* std::move "emulation".  This is as simple as it can be -- no
+   attempt is made to emulate rvalue references.  Instead relies on
+   the fact that gtl::unique_ptr has move semantics like
+   std::auto_ptr.  I.e., copy/assignment actually moves.  */
+
+template<typename T, typename D>
+unique_ptr<T, D>
+move (unique_ptr<T, D> v)
+{
+  return v;
+}
+
+#endif /* C++11 */
+
+/* Define gtl::unique_xmalloc_ptr, a gtl::unique_ptr that manages
+   xmalloc'ed memory.  */
+
+/* The deleter for gtl::unique_xmalloc_ptr.  Uses xfree.  */
+template <typename T>
+struct xfree_deleter
+{
+  void operator() (T *ptr) const { xfree (ptr); }
+};
+
+#if __cplusplus >= 201103
+
+/* In C++11, we just import the standard unique_ptr to our namespace
+   with a custom deleter.  */
+
+template<typename T> using unique_xmalloc_ptr
+  = std::unique_ptr<T, xfree_deleter<T>>;
+
+#else /* C++11 */
+
+/* In C++03, we don't have template aliases, so we need to define a
+   subclass instead, and re-define the constructors, because C++03
+   doesn't support inheriting constructors either.  */
+
+template <typename T>
+class unique_xmalloc_ptr : public unique_ptr<T, xfree_deleter<T> >
+{
+  typedef unique_ptr<T, xfree_deleter<T> > base_type;
+
+  DEFINE_GDB_UNIQUE_PTR (unique_xmalloc_ptr)
+};
+
+#endif /* C++11 */
+
+} /* namespace gtl */
+
+#endif /* GTL_UNIQUE_PTR_H */