From patchwork Tue Nov 9 17:51:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 47296 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id BE18D3858431 for ; Tue, 9 Nov 2021 17:52:23 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org BE18D3858431 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1636480343; bh=kh/R/WR46P78aLTT2cFZwXciRphSjmI2tiuhDyMVOIs=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=g57hDT5IG6cbJQIDiDDtYi111SpcJNKEvoKXiiOBjz6uapA6bAoxWZ3I0Y5eCR2D4 vy232aPdvpK4LNr2IrdhNOXXKPG0nszu/GEkaC6/2bl14RFp1NOKN/Sr/JbWZ2G0kS QreeV3kFbbJVQ96JJXiR8i8ZZnIsd7On/fuXvrRs= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 057C8385843E for ; Tue, 9 Nov 2021 17:51:34 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 057C8385843E Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-315-9ShA3hDyM_qu4eibWRIdYQ-1; Tue, 09 Nov 2021 12:51:30 -0500 X-MC-Unique: 9ShA3hDyM_qu4eibWRIdYQ-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 75A45BAF81 for ; Tue, 9 Nov 2021 17:51:29 +0000 (UTC) Received: from localhost (unknown [10.33.36.17]) by smtp.corp.redhat.com (Postfix) with ESMTP id C2A985B826 for ; Tue, 9 Nov 2021 17:51:28 +0000 (UTC) To: gcc-patches@gcc.gnu.org Subject: [PATCH] Replace gnu::unique_ptr with std::unique_ptr Date: Tue, 9 Nov 2021 17:51:27 +0000 Message-Id: <20211109175127.2736079-1-jwakely@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-14.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jonathan Wakely via Gcc-patches From: Jonathan Wakely Reply-To: Jonathan Wakely Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" 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 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. Bootstrapped and tested on powerpc64le-linux. OK for trunk? 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 instead of "unique-ptr.h". * unique-ptr-tests.cc: Removed. include/ChangeLog: * unique-ptr.h: Removed. --- gcc/Makefile.in | 1 - gcc/analyzer/engine.cc | 2 +- gcc/c-family/known-headers.cc | 2 +- gcc/c-family/name-hint.h | 12 +- gcc/c/c-decl.c | 2 +- gcc/c/c-parser.c | 2 +- gcc/cp/error.c | 2 +- gcc/cp/lex.c | 2 +- gcc/cp/name-lookup.c | 10 +- gcc/cp/parser.c | 2 +- gcc/selftest-run-tests.c | 1 - gcc/selftest.h | 1 - gcc/system.h | 8 +- gcc/unique-ptr-tests.cc | 236 -------------------- include/unique-ptr.h | 405 ---------------------------------- 15 files changed, 21 insertions(+), 667 deletions(-) delete mode 100644 gcc/unique-ptr-tests.cc delete mode 100644 include/unique-ptr.h diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 571e9c28e29..1e8e4449ffb 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1693,7 +1693,6 @@ OBJS = \ tree.o \ tristate.o \ typed-splay-tree.o \ - unique-ptr-tests.o \ valtrack.o \ value-pointer-equiv.o \ value-query.o \ diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index f21f8e5b78a..1312741bb47 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -19,7 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" -#define INCLUDE_UNIQUE_PTR +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "tree.h" diff --git a/gcc/c-family/known-headers.cc b/gcc/c-family/known-headers.cc index a3912468a8d..572cca177fa 100644 --- a/gcc/c-family/known-headers.cc +++ b/gcc/c-family/known-headers.cc @@ -18,7 +18,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" -#define INCLUDE_UNIQUE_PTR +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "c-family/c-common.h" diff --git a/gcc/c-family/name-hint.h b/gcc/c-family/name-hint.h index ea433243ba4..3141552ea59 100644 --- a/gcc/c-family/name-hint.h +++ b/gcc/c-family/name-hint.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 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 take_deferred () { return move (m_deferred); } + std::unique_ptr 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 m_deferred; + std::unique_ptr m_deferred; }; extern name_hint lookup_name_fuzzy (tree, enum lookup_name_fuzzy_kind, diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 186fa1692c1..603c1e05dd3 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -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" diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 80dd61d599e..ff5b89abfde 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -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" diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 012a4ecddf4..3e420aba3ba 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -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" diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 43abd019e6e..06de6cfe3b3 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -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" diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 035bcf51278..5be332569eb 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -19,7 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" -#define INCLUDE_UNIQUE_PTR +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "cp-tree.h" @@ -6383,7 +6383,7 @@ class namespace_limit_reached : public deferred_diagnostic { public: namespace_limit_reached (location_t loc, unsigned limit, tree name, - gnu::unique_ptr wrapped) + std::unique_ptr wrapped) : deferred_diagnostic (loc), m_limit (limit), m_name (name), m_wrapped (move (wrapped)) @@ -6403,7 +6403,7 @@ class namespace_limit_reached : public deferred_diagnostic private: unsigned m_limit; tree m_name; - gnu::unique_ptr m_wrapped; + std::unique_ptr m_wrapped; }; /* Subclass of deferred_diagnostic, for use when issuing a single suggestion. @@ -6647,7 +6647,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 @@ -6692,7 +6692,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 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 32de97b08bd..a678340d67d 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -19,7 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" -#define INCLUDE_UNIQUE_PTR +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "cp-tree.h" diff --git a/gcc/selftest-run-tests.c b/gcc/selftest-run-tests.c index 6a8f291f5dd..8eb1239b59c 100644 --- a/gcc/selftest-run-tests.c +++ b/gcc/selftest-run-tests.c @@ -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 (); diff --git a/gcc/selftest.h b/gcc/selftest.h index 24ef57cb6cc..e6c7fc35afa 100644 --- a/gcc/selftest.h +++ b/gcc/selftest.h @@ -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 (); diff --git a/gcc/system.h b/gcc/system.h index 4ac656c9c3c..2cd201743c3 100644 --- a/gcc/system.h +++ b/gcc/system.h @@ -737,12 +737,10 @@ extern int vsnprintf (char *, size_t, const char *, va_list); /* Some of the headers included by 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 #endif #ifdef INCLUDE_MALLOC_H diff --git a/gcc/unique-ptr-tests.cc b/gcc/unique-ptr-tests.cc deleted file mode 100644 index 975dd57398e..00000000000 --- a/gcc/unique-ptr-tests.cc +++ /dev/null @@ -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 -. */ - -#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. */ - -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 p; - ASSERT_EQ (NULL, p); - - gnu::unique_xmalloc_ptr 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 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 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 (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 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 (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 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 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 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 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 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 */ diff --git a/include/unique-ptr.h b/include/unique-ptr.h deleted file mode 100644 index d1b2ba5b62d..00000000000 --- a/include/unique-ptr.h +++ /dev/null @@ -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 . */ - -/* 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 -#endif - -namespace gnu -{ - -#if __cplusplus >= 201103 - -/* In C++11 mode, all we need is import the standard - std::unique_ptr. */ -template using unique_ptr = std::unique_ptr; - -/* 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 -struct default_delete -{ - void operator () (T *ptr) const { delete ptr; } -}; - -/* Specialization for arrays. Uses delete[]. */ - -template -struct default_delete -{ - void operator () (T *ptr) const { delete [] ptr; } -}; - -namespace detail -{ -/* Type used to support implicit construction from NULL: - - gnu::unique_ptr func (....) - { - return NULL; - } - - and assignment from NULL: - - gnu::unique_ptr 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 and unique_ptr. */ - -template -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 (other).release ()) {} - - /* Converting "move" constructor. Really an lvalue ref converting - constructor that actually moves. This allows constructs such as: - - unique_ptr func_returning_unique_ptr (.....); - ... - unique_ptr ptr = func_returning_unique_ptr (.....); - */ - template - unique_ptr_base (const unique_ptr_base &other) throw () - : m_ptr (const_cast &> (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 (other).release ()); - return *this; - } - - /* Converting "move" assignment. Really an lvalue ref converting - copy assignment operator that moves. See comments above. */ - template - unique_ptr_base &operator= (const unique_ptr_base &other) throw () - { - reset (const_cast &> (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 \ - TYPE (const detail::unique_ptr_base &other) throw () \ - : base_type (other) {} \ - \ - using base_type::operator=; - -/* Define single-object gnu::unique_ptr. */ - -template > -class unique_ptr : public detail::unique_ptr_base -{ - typedef detail::unique_ptr_base 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 -class unique_ptr : public detail::unique_ptr_base -{ - typedef detail::unique_ptr_base base_type; - - DEFINE_GNU_UNIQUE_PTR (unique_ptr) - -public: - /* Indexing operator. */ - T &operator[] (size_t i) const { return this->get ()[i]; } -}; - -/* Comparison operators. */ - -template -inline bool -operator== (const detail::unique_ptr_base &x, - const detail::unique_ptr_base &y) -{ return x.get() == y.get(); } - -template -inline bool -operator!= (const detail::unique_ptr_base &x, - const detail::unique_ptr_base &y) -{ return x.get() != y.get(); } - -template -inline bool -operator< (const detail::unique_ptr_base &x, - const detail::unique_ptr_base &y) -{ return x.get() < y.get (); } - -template -inline bool -operator<= (const detail::unique_ptr_base &x, - const detail::unique_ptr_base &y) -{ return !(y < x); } - -template -inline bool -operator> (const detail::unique_ptr_base &x, - const detail::unique_ptr_base &y) -{ return y < x; } - -template -inline bool -operator>= (const detail::unique_ptr_base &x, - const detail::unique_ptr_base &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 -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 -struct xmalloc_deleter -{ - void operator() (T *ptr) const { free (ptr); } -}; - -/* Same, for arrays. */ -template -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 using unique_xmalloc_ptr - = std::unique_ptr>; - -#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 -class unique_xmalloc_ptr : public unique_ptr > -{ - typedef unique_ptr > base_type; - - DEFINE_GNU_UNIQUE_PTR (unique_xmalloc_ptr) -}; - -/* Define gnu::unique_xmalloc_ptr specialization for T[]. */ - -template -class unique_xmalloc_ptr : public unique_ptr > -{ - typedef unique_ptr > base_type; - - DEFINE_GNU_UNIQUE_PTR (unique_xmalloc_ptr) -}; - -#endif /* C++11 */ - -} /* namespace gnu */ - -#endif /* GNU_UNIQUE_PTR_H */