kicad-developers team mailing list archive
-
kicad-developers team
-
Mailing list archive
-
Message #27281
[PATCH] C++14-style std::make_unique for C++11
Hi,
This is a patch to add std::make_unique to common.h when the C++
standard is C++11 (which it normally is for KiCad).
This simplifies code creating std::unique_ptr's and also means you can
generally say "never use new". It also closes a potential for
exception-unsafety concerning temporary "new"ed objects.
It's cribbed shamelessly from its proposal for C++14
(https://isocpp.org/files/papers/N3656.txt), and that's more or less
exactly how my GCC (6.3.1) implements it too. I've added the GCC
comments in for good measure.
The idea here is that when KiCad one day moves on to C++14, this file
can be removed entirely and forgetten!
Cheers,
John
From 5762fed4ae255612d244f5ab51c88c6b3c31fde4 Mon Sep 17 00:00:00 2001
From: John Beard <john.j.beard@xxxxxxxxx>
Date: Sun, 22 Jan 2017 00:03:01 +0800
Subject: [PATCH] Add C++14-style std::make_unique 'polyfill' for C++11
std::make_unique is a very useful part of the new C++ smart pointers
ecosystem, as it allows one to dispense entirely with "new" and also
provides exception safety in some cases when creating temporary
variables.
It also allows more concise code by avoiding repetition of the type:
std::make_unique<TYPE>( args );
vs
std::unique_ptr<TYPE>( new TYPE( args ) );
This commit adds a "polyfill" to provide std::make_unique when C++11 is
enabled. The implementation is that submitted to the C++ committee, and
is essentially how it is done in GCC for C++14.
The intention is to allow KiCad to use this implementation when using
C++11 and when C++14 or greater is a requirement, to remove this code
and use the compiler implementation.
---
include/common.h | 2 ++
include/make_unique.h | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 90 insertions(+)
create mode 100644 include/make_unique.h
diff --git a/include/common.h b/include/common.h
index 3ea8fad69..64ad39beb 100644
--- a/include/common.h
+++ b/include/common.h
@@ -44,6 +44,8 @@
#include <atomic>
+// C++11 "polyfill" for the C++14 std::make_unique function
+#include "make_unique.h"
class wxAboutDialogInfo;
class SEARCH_STACK;
diff --git a/include/make_unique.h b/include/make_unique.h
new file mode 100644
index 000000000..1ef20658d
--- /dev/null
+++ b/include/make_unique.h
@@ -0,0 +1,88 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2017 KiCad Developers, see AUTHORS.txt for contributors.
+ *
+ * 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 2
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * @file make_unique.h
+ * @brief Implementation of std::make_unique for pre C++14 compilation
+ * environments
+ */
+
+#ifndef MAKE_UNIQUE_H
+#define MAKE_UNIQUE_H
+
+// Define std::make_unique if the compiler is C++11, but not C++14
+// (which provides this itself)
+// When C++14 support is a KiCad pre-requisite, this entire file
+// can be removed.
+#if __cplusplus == 201103L
+
+#include <cstddef>
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+// It's a bit naughty to add things to std::, but the point is to
+// "polyfill" this function in only if std:: doesn't have it
+//
+// This implementation is the one proposed by Stephan T. Lavavej
+// in N3656: https://isocpp.org/files/papers/N3656.txt
+// This is more or less exactly how it is implemented in GCC (e.g. 6.3.1)
+// when C++14 is enabled.
+namespace std
+{
+ template<class T> struct _Unique_if {
+ typedef unique_ptr<T> _Single_object;
+ };
+
+ template<class T> struct _Unique_if<T[]> {
+ typedef unique_ptr<T[]> _Unknown_bound;
+ };
+
+ template<class T, size_t N> struct _Unique_if<T[N]> {
+ typedef void _Known_bound;
+ };
+
+ /// std::make_unique for single objects
+ template<class T, class... Args>
+ typename _Unique_if<T>::_Single_object
+ make_unique(Args&&... args) {
+ return unique_ptr<T>(new T(std::forward<Args>(args)...));
+ }
+
+ /// std::make_unique for arrays of unknown bound
+ template<class T>
+ typename _Unique_if<T>::_Unknown_bound
+ make_unique(size_t n) {
+ typedef typename remove_extent<T>::type U;
+ return unique_ptr<T>(new U[n]());
+ }
+
+ /// Disable std::make_unique for arrays of known bound
+ template<class T, class... Args>
+ typename _Unique_if<T>::_Known_bound
+ make_unique(Args&&...) = delete;
+}
+
+#endif // __cplusplus == 201103L
+
+#endif // WXSTRUCT_H_
--
2.11.0
Follow ups