← Back to team overview

kicad-developers team mailing list archive

Fwd: [PATCH] C++14-style std::make_unique for C++11

 

FWD to list

---------- Forwarded message ----------
From: John Beard <john.j.beard@xxxxxxxxx>
Date: Mon, Jan 23, 2017 at 8:36 AM
Subject: Re: [Kicad-developers] [PATCH] C++14-style std::make_unique for C++11
To: Wayne Stambaugh <stambaughw@xxxxxxxxx>


The idea with std::make_unique is essentially that when making
std::unique_ptrs, you never have to use "new" and it also makes the
code much clearer when doing so because you only need to write the
type once. Both of these aspects encourage more "modern" styles of
memory management.

I'd anticipate that make_unique would (should?) be used every time an
object is constructed into a unique_ptr, so it would save a lot of
work to do it now than wait until C++14 and change.

I have added a warning in the header for C++14. An error would cause
breakage immediately on C++14, when actually it would work, just with
an unused header. A warning will prompt for removal, but would allow
people to upgrade their own compiler standard (e.g. someone trying out
C++14/17) without having to patch the #error out.

On Mon, Jan 23, 2017 at 6:49 AM, Wayne Stambaugh <stambaughw@xxxxxxxxx> wrote:
> I'm not opposed but I agree with your assessment that it needs to not
> build when c++14 is defined.  Is this something that devs are going to
> use or is something we can push off until we are actually a c++14 project?
>
> On 1/22/2017 10:51 AM, Chris Pavlina wrote:
>> After reading about the application of std::make_unique, I like it; I am
>> not opposed to merging this. I would, however, be in favor of modifying
>> it slightly to emit a warning or error if built under C++14, so that it
>> is not forgotten if and when we do make the transition to C++14 in the
>> future.
>>
>> Is anybody else for or against this?
>>
>> On Sun, Jan 22, 2017 at 12:38:07AM +0800, John Beard wrote:
>>> 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
>>
>>
>> _______________________________________________
>> Mailing list: https://launchpad.net/~kicad-developers
>> Post to     : kicad-developers@xxxxxxxxxxxxxxxxxxx
>> Unsubscribe : https://launchpad.net/~kicad-developers
>> More help   : https://help.launchpad.net/ListHelp
>>
>
>
> _______________________________________________
> Mailing list: https://launchpad.net/~kicad-developers
> Post to     : kicad-developers@xxxxxxxxxxxxxxxxxxx
> Unsubscribe : https://launchpad.net/~kicad-developers
> More help   : https://help.launchpad.net/ListHelp
From 2a75bab89393e607ea26ef796da3ec997da7fb82 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 1/4] 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 | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 95 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..97f1a4360
--- /dev/null
+++ b/include/make_unique.h
@@ -0,0 +1,93 @@
+/*
+ * 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;
+}
+
+#else // __cplusplus == ...
+
+// After switching to C++14, this entire header should be removed
+#warning "make_unique.h still present, but in C++14 mode - ignoring and using compiler implementation."
+
+#endif // __cplusplus == ...
+
+#endif  // WXSTRUCT_H_
-- 
2.11.0


References