This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Add gnu::unique_ptr


On Fri, Oct 13, 2017 at 2:40 AM, David Malcolm <dmalcolm@redhat.com> wrote:
> From: Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
>
> I had a go at updating Trevor's unique_ptr patch from July
> ( https://gcc.gnu.org/ml/gcc-patches/2017-07/msg02084.html )
>
> One of the sticking points was what to call the namespace; there was
> wariness about using "gtl" as the name.
>
> Richi proposed (https://gcc.gnu.org/ml/gcc-patches/2017-09/msg00155.html):
>> If it should be short use g::.  We can also use gnu:: I guess and I
>> agree gnutools:: is a little long (similar to libiberty::).  Maybe
>> gt:: as a short-hand for gnutools.
>
> Pedro noted (https://gcc.gnu.org/ml/gcc-patches/2017-09/msg00157.html):
>> Exactly 3 letters has the nice property of making s/gtl::foo/std::foo/
>> super trivial down the road; you don't have to care about reindenting
>> stuff
>
> Hence this version of the patch uses "gnu::" - 3 letters, one of the
> ones Richi proposed, and *not* a match for ".tl" (e.g. "gtl");
> (FWIW personally "gnu::" is my favorite, followed by "gcc::").
>
> The include/unique-ptr.h in this patch is identical to that posted
> by Trevor in July, with the following changes (by me):
> - renaming of "gtl" to "gnu"
> - renaming of DEFINE_GDB_UNIQUE_PTR to DEFINE_GNU_UNIQUE_PTR
> - renaming of xfree_deleter to xmalloc_deleter, and making it
>   use "free" rather than "xfree" (which doesn't exist)
>
> I also went and added a gcc/unique-ptr-tests.cc file containing
> selftests (my thinking here is that although std::unique_ptr ought
> to already be well-tested, we need to ensure that the fallback
> implementation is sane when building with C++ prior to C++11).
>
> Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu,
> using gcc 4.8 for the initial bootstrap (hence testing both gnu+03
> and then gnu++14 in the selftests, for stage 1 and stages 2 and 3
> respectively).
>
> I also manually tested selftests with both gcc 4.8 and trunk on
> the same hardware (again, to exercise both the with/without C++11
> behavior).
>
> Tested with "make selftest-valgrind" (no new issues).
>
> OK for trunk?

Ok if the gdb folks approve (and will change to this version).

Thanks,
Richard.

> Motivation/use-cases:
> (a) I have an updated version of the
> name_hint/deferred_diagnostic patch kit, which uses this (rather
> than the refcounting used by
> https://gcc.gnu.org/ml/gcc-patches/2017-05/msg00439.html ); and
> (b) having this available ought to allow various other cleanups
> e.g. the example ones identified by Trevor here:
>   https://gcc.gnu.org/ml/gcc-patches/2017-07/msg02085.html
>
> Thanks
> Dave
>
>
> Blurb from Trevor:
>
> 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.
>
> Combined ChangeLog follows:
>
> gcc/ChangeLog:
>
>         David Malcolm <dmalcolm@redhat.com>
>
>         * Makefile.in (OBJS): Add unique-ptr-tests.o.
>         * selftest-run-tests.c (selftest::run_tests): Call
>         selftest::unique_ptr_tests_cc_tests.
>         * selftest.h (selftest::unique_ptr_tests_cc_tests): New decl.
>         * unique-ptr-tests.cc: New file.
>
> include/ChangeLog:
>
>         Trevor Saunders  <tbsaunde+gcc@tbsaunde.org>
>         David Malcolm <dmalcolm@redhat.com>
>
>         * unique-ptr.h: New file.
> ---
>  gcc/Makefile.in          |   1 +
>  gcc/selftest-run-tests.c |   1 +
>  gcc/selftest.h           |   1 +
>  gcc/unique-ptr-tests.cc  | 177 ++++++++++++++++++++++
>  include/unique-ptr.h     | 386 +++++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 566 insertions(+)
>  create mode 100644 gcc/unique-ptr-tests.cc
>  create mode 100644 include/unique-ptr.h
>
> diff --git a/gcc/Makefile.in b/gcc/Makefile.in
> index 878ce7b..2809619 100644
> --- a/gcc/Makefile.in
> +++ b/gcc/Makefile.in
> @@ -1568,6 +1568,7 @@ OBJS = \
>         tree-vrp.o \
>         tree.o \
>         typed-splay-tree.o \
> +       unique-ptr-tests.o \
>         valtrack.o \
>         value-prof.o \
>         var-tracking.o \
> diff --git a/gcc/selftest-run-tests.c b/gcc/selftest-run-tests.c
> index 30e476d..b05e0fc 100644
> --- a/gcc/selftest-run-tests.c
> +++ b/gcc/selftest-run-tests.c
> @@ -66,6 +66,7 @@ selftest::run_tests ()
>    sreal_c_tests ();
>    fibonacci_heap_c_tests ();
>    typed_splay_tree_c_tests ();
> +  unique_ptr_tests_cc_tests ();
>
>    /* Mid-level data structures.  */
>    input_c_tests ();
> diff --git a/gcc/selftest.h b/gcc/selftest.h
> index 96eccac..adc0b68 100644
> --- a/gcc/selftest.h
> +++ b/gcc/selftest.h
> @@ -194,6 +194,7 @@ extern void store_merging_c_tests ();
>  extern void typed_splay_tree_c_tests ();
>  extern void tree_c_tests ();
>  extern void tree_cfg_c_tests ();
> +extern void unique_ptr_tests_cc_tests ();
>  extern void vec_c_tests ();
>  extern void wide_int_cc_tests ();
>  extern void predict_c_tests ();
> diff --git a/gcc/unique-ptr-tests.cc b/gcc/unique-ptr-tests.cc
> new file mode 100644
> index 0000000..df18467
> --- /dev/null
> +++ b/gcc/unique-ptr-tests.cc
> @@ -0,0 +1,177 @@
> +/* Unit tests for unique-ptr.h.
> +   Copyright (C) 2017 Free Software Foundation, Inc.
> +
> +This file is part of GCC.
> +
> +GCC 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, or (at your option) any later
> +version.
> +
> +GCC 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 GCC; see the file COPYING3.  If not see
> +<http://www.gnu.org/licenses/>.  */
> +
> +#include "config.h"
> +#include "system.h"
> +#include "coretypes.h"
> +#include "unique-ptr.h"
> +#include "selftest.h"
> +
> +#if CHECKING_P
> +
> +namespace selftest {
> +
> +namespace {
> +
> +/* A class for counting ctor and dtor invocations.  */
> +
> +struct stats
> +{
> +  stats () : ctor_count (0), dtor_count (0) {}
> +
> +  int ctor_count;
> +  int dtor_count;
> +};
> +
> +/* A class that uses "stats" to track its ctor and dtor invocations.  */
> +
> +class foo
> +{
> +public:
> +  foo (stats &s) : m_s (s) { ++m_s.ctor_count; }
> +  ~foo () { ++m_s.dtor_count; }
> +
> +  int example_method () const { return 42; }
> +
> +private:
> +  foo (const foo&);
> +  foo & operator= (const foo &);
> +
> +private:
> +  stats &m_s;
> +};
> +
> +} // anonymous namespace
> +
> +/* Verify that the default ctor inits ptrs to NULL.  */
> +
> +static void
> +test_null_ptr ()
> +{
> +  gnu::unique_ptr<void *> p;
> +  ASSERT_EQ (NULL, p);
> +
> +  gnu::unique_xmalloc_ptr<void *> q;
> +  ASSERT_EQ (NULL, q);
> +}
> +
> +/* Verify that deletion happens when a unique_ptr goes out of scope.  */
> +
> +static void
> +test_implicit_deletion ()
> +{
> +  stats s;
> +  ASSERT_EQ (0, s.ctor_count);
> +  ASSERT_EQ (0, s.dtor_count);
> +
> +  {
> +    gnu::unique_ptr<foo> f (new foo (s));
> +    ASSERT_NE (NULL, f);
> +    ASSERT_EQ (1, s.ctor_count);
> +    ASSERT_EQ (0, s.dtor_count);
> +  }
> +
> +  /* Verify that the foo was implicitly deleted.  */
> +  ASSERT_EQ (1, s.ctor_count);
> +  ASSERT_EQ (1, s.dtor_count);
> +}
> +
> +/* Verify that we can assign to a NULL unique_ptr.  */
> +
> +static void
> +test_overwrite_of_null ()
> +{
> +  stats s;
> +  ASSERT_EQ (0, s.ctor_count);
> +  ASSERT_EQ (0, s.dtor_count);
> +
> +  {
> +    gnu::unique_ptr<foo> f;
> +    ASSERT_EQ (NULL, f);
> +    ASSERT_EQ (0, s.ctor_count);
> +    ASSERT_EQ (0, s.dtor_count);
> +
> +    /* Overwrite with a non-NULL value.  */
> +    f = gnu::unique_ptr<foo> (new foo (s));
> +    ASSERT_EQ (1, s.ctor_count);
> +    ASSERT_EQ (0, s.dtor_count);
> +  }
> +
> +  /* Verify that the foo is implicitly deleted.  */
> +  ASSERT_EQ (1, s.ctor_count);
> +  ASSERT_EQ (1, s.dtor_count);
> +}
> +
> +/* Verify that we can assign to a non-NULL unique_ptr.  */
> +
> +static void
> +test_overwrite_of_non_null ()
> +{
> +  stats s;
> +  ASSERT_EQ (0, s.ctor_count);
> +  ASSERT_EQ (0, s.dtor_count);
> +
> +  {
> +    gnu::unique_ptr<foo> f (new foo (s));
> +    ASSERT_NE (NULL, f);
> +    ASSERT_EQ (1, s.ctor_count);
> +    ASSERT_EQ (0, s.dtor_count);
> +
> +    /* Overwrite with a different value.  */
> +    f = gnu::unique_ptr<foo> (new foo (s));
> +    ASSERT_EQ (2, s.ctor_count);
> +    ASSERT_EQ (1, s.dtor_count);
> +  }
> +
> +  /* Verify that the 2nd foo was implicitly deleted.  */
> +  ASSERT_EQ (2, s.ctor_count);
> +  ASSERT_EQ (2, s.dtor_count);
> +}
> +
> +/* Verify that unique_ptr's overloaded ops work.  */
> +
> +static void
> +test_overloaded_ops ()
> +{
> +  stats s;
> +  gnu::unique_ptr<foo> f (new foo (s));
> +  ASSERT_EQ (42, f->example_method ());
> +  ASSERT_EQ (42, (*f).example_method ());
> +  ASSERT_EQ (f, f);
> +  ASSERT_NE (NULL, f.get ());
> +
> +  gnu::unique_ptr<foo> g (new foo (s));
> +  ASSERT_NE (f, g);
> +}
> +
> +/* Run all of the selftests within this file.  */
> +
> +void
> +unique_ptr_tests_cc_tests ()
> +{
> +  test_null_ptr ();
> +  test_implicit_deletion ();
> +  test_overwrite_of_null ();
> +  test_overwrite_of_non_null ();
> +  test_overloaded_ops ();
> +}
> +
> +} // namespace selftest
> +
> +#endif /* #if CHECKING_P */
> diff --git a/include/unique-ptr.h b/include/unique-ptr.h
> new file mode 100644
> index 0000000..eddb001
> --- /dev/null
> +++ b/include/unique-ptr.h
> @@ -0,0 +1,386 @@
> +/* gnu::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/>.  */
> +
> +/* gnu::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, gnu::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 gnu::unique_ptr partial
> +   specialization that uses a custom (stateless) deleter:
> +   gnu::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 gnu::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, gnu::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 GNU_UNIQUE_PTR_H
> +#define GNU_UNIQUE_PTR_H 1
> +
> +#include <memory>
> +
> +namespace gnu
> +{
> +
> +#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 gnu::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:
> +
> +     gnu::unique_ptr<foo> func (....)
> +     {
> +     return NULL;
> +     }
> +
> +   and assignment from NULL:
> +
> +     gnu::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_GNU_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 gnu::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_GNU_UNIQUE_PTR (unique_ptr)
> +
> +public:
> +  /* Dereferencing.  */
> +  T &operator* () const throw () { return *this->get (); }
> +  T *operator-> () const throw () { return this->get (); }
> +};
> +
> +/* Define gnu::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_GNU_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 gnu::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 gnu::unique_xmalloc_ptr, a gnu::unique_ptr that manages
> +   xmalloc'ed memory.  */
> +
> +/* The deleter for gnu::unique_xmalloc_ptr.  Uses free.  */
> +template <typename T>
> +struct xmalloc_deleter
> +{
> +  void operator() (T *ptr) const { free (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, xmalloc_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, xmalloc_deleter<T> >
> +{
> +  typedef unique_ptr<T, xmalloc_deleter<T> > base_type;
> +
> +  DEFINE_GNU_UNIQUE_PTR (unique_xmalloc_ptr)
> +};
> +
> +#endif /* C++11 */
> +
> +} /* namespace gnu */
> +
> +#endif /* GNU_UNIQUE_PTR_H */
> --
> 1.8.5.3
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]