Replace gnu::unique_ptr with std::unique_ptr
Now that GCC is compiled as C++11 there is no need to keep the C++03 implementation of gnu::unique_ptr. This removes the unique-ptr.h header and replaces it with <memory> in system.h, and changes the INCLUDE_UNIQUE_PTR macro to INCLUDE_MEMORY. Uses of gnu::unique_ptr and gnu::move can be replaced with std::unique_ptr and std::move. There are no uses of unique_xmalloc_ptr or xmalloc_deleter in GCC. gcc/analyzer/ChangeLog: * engine.cc: Define INCLUDE_MEMORY instead of INCLUDE_UNIQUE_PTR. gcc/c-family/ChangeLog: * known-headers.cc: Define INCLUDE_MEMORY instead of INCLUDE_UNIQUE_PTR. * name-hint.h: Likewise. (class name_hint): Use std::unique_ptr instead of gnu::unique_ptr. gcc/c/ChangeLog: * c-decl.c: Define INCLUDE_MEMORY instead of INCLUDE_UNIQUE_PTR. * c-parser.c: Likewise. gcc/cp/ChangeLog: * error.c: Define INCLUDE_MEMORY instead of INCLUDE_UNIQUE_PTR. * lex.c: Likewise. * name-lookup.c: Likewise. (class namespace_limit_reached): Use std::unique_ptr instead of gnu::unique_ptr. (suggest_alternatives_for): Use std::move instead of gnu::move. (suggest_alternatives_in_other_namespaces): Likewise. * parser.c: Define INCLUDE_MEMORY instead of INCLUDE_UNIQUE_PTR. gcc/ChangeLog: * Makefile.in: Remove unique-ptr-tests.o. * selftest-run-tests.c (selftest::run_tests): Remove unique_ptr_tests_cc_tests. * selftest.h (unique_ptr_tests_cc_tests): Remove. * system.h: Check INCLUDE_MEMORY instead of INCLUDE_UNIQUE_PTR and include <memory> instead of "unique-ptr.h". * unique-ptr-tests.cc: Removed. include/ChangeLog: * unique-ptr.h: Removed.
This commit is contained in:
parent
0b52083ea2
commit
b8f7ff76d6
15 changed files with 21 additions and 667 deletions
|
@ -1699,7 +1699,6 @@ OBJS = \
|
|||
tree.o \
|
||||
tristate.o \
|
||||
typed-splay-tree.o \
|
||||
unique-ptr-tests.o \
|
||||
valtrack.o \
|
||||
value-pointer-equiv.o \
|
||||
value-query.o \
|
||||
|
|
|
@ -19,7 +19,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "config.h"
|
||||
#define INCLUDE_UNIQUE_PTR
|
||||
#define INCLUDE_MEMORY
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tree.h"
|
||||
|
|
|
@ -18,7 +18,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "config.h"
|
||||
#define INCLUDE_UNIQUE_PTR
|
||||
#define INCLUDE_MEMORY
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "c-family/c-common.h"
|
||||
|
|
|
@ -20,12 +20,12 @@ along with GCC; see the file COPYING3. If not see
|
|||
#ifndef GCC_NAME_HINT_H
|
||||
#define GCC_NAME_HINT_H
|
||||
|
||||
/* This header uses gnu::unique_ptr, but unique-ptr.h can't be directly
|
||||
/* This header uses std::unique_ptr, but <memory> can't be directly
|
||||
included due to issues with macros. Hence it must be included from
|
||||
system.h by defining INCLUDE_UNIQUE_PTR in any source file using it. */
|
||||
system.h by defining INCLUDE_MEMORY in any source file using it. */
|
||||
|
||||
#ifndef GNU_UNIQUE_PTR_H
|
||||
# error "You must define INCLUDE_UNIQUE_PTR before including system.h to use name-hint.h"
|
||||
#ifndef INCLUDE_MEMORY
|
||||
# error "You must define INCLUDE_MEMORY before including system.h to use name-hint.h"
|
||||
#endif
|
||||
|
||||
enum lookup_name_fuzzy_kind {
|
||||
|
@ -106,7 +106,7 @@ public:
|
|||
|
||||
/* Take ownership of this name_hint's deferred_diagnostic, for use
|
||||
in chaining up deferred diagnostics. */
|
||||
gnu::unique_ptr<deferred_diagnostic> take_deferred () { return move (m_deferred); }
|
||||
std::unique_ptr<deferred_diagnostic> take_deferred () { return move (m_deferred); }
|
||||
|
||||
/* Call this on a name_hint if the corresponding warning was not emitted,
|
||||
in which case we should also not emit the deferred_diagnostic. */
|
||||
|
@ -119,7 +119,7 @@ public:
|
|||
|
||||
private:
|
||||
const char *m_suggestion;
|
||||
gnu::unique_ptr<deferred_diagnostic> m_deferred;
|
||||
std::unique_ptr<deferred_diagnostic> m_deferred;
|
||||
};
|
||||
|
||||
extern name_hint lookup_name_fuzzy (tree, enum lookup_name_fuzzy_kind,
|
||||
|
|
|
@ -26,7 +26,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
|
||||
#include "config.h"
|
||||
#define INCLUDE_STRING
|
||||
#define INCLUDE_UNIQUE_PTR
|
||||
#define INCLUDE_MEMORY
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "target.h"
|
||||
|
|
|
@ -36,7 +36,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
location rather than implicitly using input_location. */
|
||||
|
||||
#include "config.h"
|
||||
#define INCLUDE_UNIQUE_PTR
|
||||
#define INCLUDE_MEMORY
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "target.h"
|
||||
|
|
|
@ -19,7 +19,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
|
||||
#include "config.h"
|
||||
/* For use with name_hint. */
|
||||
#define INCLUDE_UNIQUE_PTR
|
||||
#define INCLUDE_MEMORY
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "cp-tree.h"
|
||||
|
|
|
@ -23,7 +23,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
|
||||
#include "config.h"
|
||||
/* For use with name_hint. */
|
||||
#define INCLUDE_UNIQUE_PTR
|
||||
#define INCLUDE_MEMORY
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "cp-tree.h"
|
||||
|
|
|
@ -19,7 +19,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "config.h"
|
||||
#define INCLUDE_UNIQUE_PTR
|
||||
#define INCLUDE_MEMORY
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "cp-tree.h"
|
||||
|
@ -6340,7 +6340,7 @@ class namespace_limit_reached : public deferred_diagnostic
|
|||
{
|
||||
public:
|
||||
namespace_limit_reached (location_t loc, unsigned limit, tree name,
|
||||
gnu::unique_ptr<deferred_diagnostic> wrapped)
|
||||
std::unique_ptr<deferred_diagnostic> wrapped)
|
||||
: deferred_diagnostic (loc),
|
||||
m_limit (limit), m_name (name),
|
||||
m_wrapped (move (wrapped))
|
||||
|
@ -6360,7 +6360,7 @@ class namespace_limit_reached : public deferred_diagnostic
|
|||
private:
|
||||
unsigned m_limit;
|
||||
tree m_name;
|
||||
gnu::unique_ptr<deferred_diagnostic> m_wrapped;
|
||||
std::unique_ptr<deferred_diagnostic> m_wrapped;
|
||||
};
|
||||
|
||||
/* Subclass of deferred_diagnostic, for use when issuing a single suggestion.
|
||||
|
@ -6604,7 +6604,7 @@ suggest_alternatives_for (location_t location, tree name,
|
|||
if (!result)
|
||||
result = suggest_alternatives_for_1 (location, name, suggest_misspellings);
|
||||
|
||||
return ns_hints.maybe_decorate_with_limit (gnu::move (result));
|
||||
return ns_hints.maybe_decorate_with_limit (std::move (result));
|
||||
}
|
||||
|
||||
/* The second half of suggest_alternatives_for, for when no exact matches
|
||||
|
@ -6649,7 +6649,7 @@ suggest_alternatives_in_other_namespaces (location_t location, tree name)
|
|||
|
||||
name_hint result = ns_hints.convert_candidates_to_name_hint ();
|
||||
|
||||
return ns_hints.maybe_decorate_with_limit (gnu::move (result));
|
||||
return ns_hints.maybe_decorate_with_limit (std::move (result));
|
||||
}
|
||||
|
||||
/* A well-known name within the C++ standard library, returned by
|
||||
|
|
|
@ -19,7 +19,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "config.h"
|
||||
#define INCLUDE_UNIQUE_PTR
|
||||
#define INCLUDE_MEMORY
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "cp-tree.h"
|
||||
|
|
|
@ -71,7 +71,6 @@ selftest::run_tests ()
|
|||
sreal_c_tests ();
|
||||
fibonacci_heap_c_tests ();
|
||||
typed_splay_tree_c_tests ();
|
||||
unique_ptr_tests_cc_tests ();
|
||||
opt_proposer_c_tests ();
|
||||
opts_c_tests ();
|
||||
json_cc_tests ();
|
||||
|
|
|
@ -262,7 +262,6 @@ extern void tree_cfg_c_tests ();
|
|||
extern void tree_diagnostic_path_cc_tests ();
|
||||
extern void tristate_cc_tests ();
|
||||
extern void typed_splay_tree_c_tests ();
|
||||
extern void unique_ptr_tests_cc_tests ();
|
||||
extern void vec_c_tests ();
|
||||
extern void vec_perm_indices_c_tests ();
|
||||
extern void wide_int_cc_tests ();
|
||||
|
|
|
@ -737,12 +737,10 @@ extern int vsnprintf (char *, size_t, const char *, va_list);
|
|||
|
||||
/* Some of the headers included by <memory> can use "abort" within a
|
||||
namespace, e.g. "_VSTD::abort();", which fails after we use the
|
||||
preprocessor to redefine "abort" as "fancy_abort" below.
|
||||
Given that unique-ptr.h can use "free", we need to do this after "free"
|
||||
is declared but before "abort" is overridden. */
|
||||
preprocessor to redefine "abort" as "fancy_abort" below. */
|
||||
|
||||
#ifdef INCLUDE_UNIQUE_PTR
|
||||
# include "unique-ptr.h"
|
||||
#ifdef INCLUDE_MEMORY
|
||||
# include <memory>
|
||||
#endif
|
||||
|
||||
#ifdef INCLUDE_MALLOC_H
|
||||
|
|
|
@ -1,236 +0,0 @@
|
|||
/* Unit tests for unique-ptr.h.
|
||||
Copyright (C) 2017-2021 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"
|
||||
#define INCLUDE_UNIQUE_PTR
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "selftest.h"
|
||||
|
||||
#if CHECKING_P
|
||||
|
||||
namespace selftest {
|
||||
|
||||
namespace {
|
||||
|
||||
/* A class for counting ctor and dtor invocations. */
|
||||
|
||||
class stats
|
||||
{
|
||||
public:
|
||||
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;
|
||||
};
|
||||
|
||||
/* A struct for testing unique_ptr<T[]>. */
|
||||
|
||||
class has_default_ctor
|
||||
{
|
||||
public:
|
||||
has_default_ctor () : m_field (42) {}
|
||||
int m_field;
|
||||
};
|
||||
|
||||
/* A dummy struct for testing unique_xmalloc_ptr. */
|
||||
|
||||
struct dummy
|
||||
{
|
||||
int field;
|
||||
};
|
||||
|
||||
} // 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);
|
||||
}
|
||||
|
||||
/* Verify that the gnu::unique_ptr specialization for T[] works. */
|
||||
|
||||
static void
|
||||
test_array_new ()
|
||||
{
|
||||
const int num = 10;
|
||||
gnu::unique_ptr<has_default_ctor[]> p (new has_default_ctor[num]);
|
||||
ASSERT_NE (NULL, p.get ());
|
||||
/* Verify that operator[] works, and that the default ctor was called
|
||||
on each element. */
|
||||
for (int i = 0; i < num; i++)
|
||||
ASSERT_EQ (42, p[i].m_field);
|
||||
}
|
||||
|
||||
/* Verify that gnu::unique_xmalloc_ptr works. */
|
||||
|
||||
static void
|
||||
test_xmalloc ()
|
||||
{
|
||||
gnu::unique_xmalloc_ptr<dummy> p (XNEW (dummy));
|
||||
ASSERT_NE (NULL, p.get ());
|
||||
}
|
||||
|
||||
/* Verify the gnu::unique_xmalloc_ptr specialization for T[]. */
|
||||
|
||||
static void
|
||||
test_xmalloc_array ()
|
||||
{
|
||||
const int num = 10;
|
||||
gnu::unique_xmalloc_ptr<dummy[]> p (XNEWVEC (dummy, num));
|
||||
ASSERT_NE (NULL, p.get ());
|
||||
|
||||
/* Verify that operator[] works. */
|
||||
for (int i = 0; i < num; i++)
|
||||
p[i].field = 42;
|
||||
for (int i = 0; i < num; i++)
|
||||
ASSERT_EQ (42, p[i].field);
|
||||
}
|
||||
|
||||
/* 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 ();
|
||||
test_array_new ();
|
||||
test_xmalloc ();
|
||||
test_xmalloc_array ();
|
||||
}
|
||||
|
||||
} // namespace selftest
|
||||
|
||||
#endif /* #if CHECKING_P */
|
|
@ -1,405 +0,0 @@
|
|||
/* gnu::unique_ptr, a simple std::unique_ptr replacement for C++03.
|
||||
|
||||
Copyright (C) 2007-2021 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
|
||||
|
||||
#if __cplusplus >= 201103
|
||||
# include <memory>
|
||||
#endif
|
||||
|
||||
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. This relies on T
|
||||
having move semantics like std::auto_ptr.
|
||||
I.e., copy/assignment actually moves. */
|
||||
|
||||
template<typename T>
|
||||
const T&
|
||||
move (T& 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); }
|
||||
};
|
||||
|
||||
/* Same, for arrays. */
|
||||
template <typename T>
|
||||
struct xmalloc_deleter<T[]>
|
||||
{
|
||||
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)
|
||||
};
|
||||
|
||||
/* Define gnu::unique_xmalloc_ptr specialization for T[]. */
|
||||
|
||||
template <typename T>
|
||||
class unique_xmalloc_ptr<T[]> : 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 */
|
Loading…
Add table
Reference in a new issue