From 66a0fa20003e93a09d1430476dc1ff541601a4cc Mon Sep 17 00:00:00 2001
From: Sam Yates <halfflat@gmail.com>
Date: Thu, 16 Jun 2016 14:20:17 +0200
Subject: [PATCH] Experiments in code formatting continued.

---
 src/util/meta.hpp          |  36 +++++
 src/util/optional.hpp      | 267 +++++++++++++++++--------------------
 src/util/uninitialized.hpp |  93 ++++++-------
 3 files changed, 202 insertions(+), 194 deletions(-)
 create mode 100644 src/util/meta.hpp

diff --git a/src/util/meta.hpp b/src/util/meta.hpp
new file mode 100644
index 00000000..2e22e31c
--- /dev/null
+++ b/src/util/meta.hpp
@@ -0,0 +1,36 @@
+#pragma once
+
+/* Type utilities and convenience expressions.  */
+
+#include <type_traits>
+
+namespace nest {
+namespace mc {
+namespace util {
+
+// Until C++14 ...
+
+template <typename T>
+using result_of_t = typename std::result_of<T>::type;
+
+template <bool V>
+using enable_if_t = typename std::enable_if<V>::type;
+
+// Convenience short cuts
+
+template <typename T>
+using enable_if_copy_constructible_t =
+    enable_if_t<std::is_copy_constructible<T>::value>;
+
+template <typename T>
+using enable_if_move_constructible_t =
+    enable_if_t<std::is_move_constructible<T>::value>;
+
+template <typename... T>
+using enable_if_constructible_t =
+    enable_if_t<std::is_constructible<T...>::value>;
+
+
+} // namespace util
+} // namespace mc
+} // namespace nest
diff --git a/src/util/optional.hpp b/src/util/optional.hpp
index d23b5b8b..1935a6b3 100644
--- a/src/util/optional.hpp
+++ b/src/util/optional.hpp
@@ -1,25 +1,25 @@
 #pragma once
 
-/*! \file optional.h
- *  \brief An option class with a monadic interface.
+/* An option class with a monadic interface.
  *
- *  The std::option<T> class was proposed for inclusion into C++14, but was
- *  ultimately rejected. (See N3672 proposal for details.) This class offers
- *  similar functionality, namely a class that can represent a value (or
- *  reference), or nothing at all.
+ * The std::option<T> class was proposed for inclusion into C++14, but was
+ * ultimately rejected. (See N3672 proposal for details.) This class offers
+ * similar functionality, namely a class that can represent a value (or
+ * reference), or nothing at all.
  *
- *  In addition, this class offers monadic and monoidal bindings, allowing
- *  the chaining of operations any one of which might represent failure with
- *  an unset optional value.
+ * In addition, this class offers monadic and monoidal bindings, allowing
+ * the chaining of operations any one of which might represent failure with
+ * an unset optional value.
  *
- *  One point of difference between the proposal N3672 and this implementation
- *  is the lack of constexpr versions of the methods and constructors.
+ * One point of difference between the proposal N3672 and this implementation
+ * is the lack of constexpr versions of the methods and constructors.
  */
 
 #include <type_traits>
 #include <stdexcept>
 #include <utility>
 
+#include "util/meta.hpp"
 #include "util/uninitialized.hpp"
 
 namespace nest {
@@ -43,7 +43,7 @@ struct optional_invalid_dereference: std::runtime_error {
         : std::runtime_error(what_str)
     {}
 
-    optional_invalid_dereference()\
+    optional_invalid_dereference()
         : std::runtime_error("derefernce of optional<void> value")
     {}
 };
@@ -52,69 +52,61 @@ struct nothing_t {};
 constexpr nothing_t nothing{};
 
 namespace detail {
-    // the only change I make is to add an underscore after lift_type_
     template <typename Y>
-    struct lift_type_
-    { using type=optional<Y>; };
+    struct lift_type {
+        using type = optional<Y>;
+    };
 
     template <typename Y>
-    struct lift_type_<optional<Y>>
-    { using type=optional<Y>; };
+    struct lift_type<optional<Y>> {
+        using type = optional<Y>;
+    };
 
-    // ... then use an alias template to remove the need for a ::type in user code
-    // this is in the same vain as the metafunctions like std::decay_t that were introduced in C++14
     template <typename Y>
-    using lift_type = typename lift_type_<Y>::type;
+    using lift_type_t = typename lift_type<Y>::type;
 
     struct optional_tag {};
 
-    // constexpr function instead
     template <typename X>
-    constexpr bool is_optional() {
-        return std::is_base_of<optional_tag, typename std::decay<X>::type>::value;
-    }
+    using is_optional = std::is_base_of<optional_tag, typename std::decay<X>::type>;
 
-    // you were kind of using the same pattern here...
     template <typename D,typename X>
-    struct wrapped_type_
-    { using type=X; };
+    struct wrapped_type_impl {
+        using type = X;
+    };
 
     template <typename D,typename X>
-    struct wrapped_type_<optional<D>,X>
-    { using type=D; };
+    struct wrapped_type_impl<optional<D>,X> {
+        using type = D;
+    };
+
+    template <typename X>
+    struct wrapped_type {
+       using type = typename wrapped_type_impl<typename std::decay<X>::type,X>::type;
+    };
 
-    // but we can simplify the following with an alias template
-    //template <typename X> struct wrapped_type { using type=typename wrapped_type_<typename std::decay<X>::type,X>::type; };
     template <typename X>
-    using wrapped_type =
-        typename wrapped_type_<typename std::decay<X>::type, X>::type;
+    using wrapped_type_t = typename wrapped_type<X>::type;
 
     template <typename X>
     struct optional_base: detail::optional_tag {
         template <typename Y> friend struct optional;
 
     protected:
-        // D is used throughout, so maybe give it a more descriptive name like unitinitialized_type ?
-        // whatever, I have the style of using CamelCase for template parameters, and lower case with underscore
-        // for "typedefed" types inside the class
-        using D=util::uninitialized<X>;
+        using data_type = util::uninitialized<X>;
 
     public:
-        // sorry, I like spaces around = signs and spaces after commas
-        using reference_type = typename D::reference_type;
-        using const_reference_type = typename D::const_reference_type;
-        using pointer_type = typename D::pointer_type;
-        using const_pointer_type = typename D::const_pointer_type;
+        using reference_type = typename data_type::reference_type;
+        using const_reference_type = typename data_type::const_reference_type;
+        using pointer_type = typename data_type::pointer_type;
+        using const_pointer_type = typename data_type::const_pointer_type;
 
     protected:
         bool set;
-        D data;
+        data_type data;
 
-        // don't be afraid of vertical space
-        optional_base() : set(false)
-        {}
+        optional_base() : set(false) {}
 
-        // I am not too fussy, you could get away with this...
         template <typename T>
         optional_base(bool set_, T&& init) : set(set_) {
             if (set) {
@@ -122,13 +114,10 @@ namespace detail {
             }
         }
 
-        // I could be persuaded to go one line for these, but a bit of vertical alignment helps
         reference_type       ref()       { return data.ref(); }
         const_reference_type ref() const { return data.cref(); }
 
     public:
-        // I know that this is annoying..
-        //~optional_base() { if (set) data.destruct(); }
         ~optional_base() {
             if (set) {
                 data.destruct();
@@ -142,6 +131,7 @@ namespace detail {
         reference_type       operator*()       { return ref(); }
 
         reference_type get() {
+            // I find this super verbose :(
             if (set) {
                 return ref();
             }
@@ -159,18 +149,15 @@ namespace detail {
             }
         }
 
-        // how about the following as a compromise for simple one-liners?
-        explicit operator bool() const
-        { return set; }
+        explicit operator bool() const { return set; }
 
-        // though this is just one more line...
         template <typename Y>
-        bool operator==(const Y &y) const {
+        bool operator==(const Y& y) const {
             return set && ref()==y;
         }
 
         template <typename Y>
-        bool operator==(const optional<Y> &o) const {
+        bool operator==(const optional<Y>& o) const {
             return (set && o.set && ref()==o.ref()) || (!set && !o.set);
         }
 
@@ -178,45 +165,42 @@ namespace detail {
             if (set) {
                 data.destruct();
             }
-            set=false;
+            set = false;
         }
 
-        // see how we remove another typename and another ::type below
         template <typename F>
-        auto bind(F &&f) -> lift_type<decltype(data.apply(std::forward<F>(f)))> {
+        auto bind(F&& f) -> lift_type_t<decltype(data.apply(std::forward<F>(f)))> {
             using F_result_type = decltype(data.apply(std::forward<F>(f)));
-            using result_type = lift_type<F_result_type>;
+            using result_type = lift_type_t<F_result_type>;
 
             if (!set) {
                 return result_type();
             }
-            else return bind_impl<result_type,std::is_same<F_result_type,void>::value>::bind(data,std::forward<F>(f));
+
+            return bind_impl<result_type, std::is_void<F_result_type>::value>::
+                       bind(data, std::forward<F>(f));
         }
 
         template <typename F>
-        auto bind(F &&f) const -> lift_type<decltype(data.apply(std::forward<F>(f)))> {
+        auto bind(F&& f) const -> lift_type_t<decltype(data.apply(std::forward<F>(f)))> {
             using F_result_type = decltype(data.apply(std::forward<F>(f)));
-            using result_type = lift_type<F_result_type>;
+            using result_type = lift_type_t<F_result_type>;
 
             if (!set) {
                 return result_type();
             }
-            else {
-                return
-                    bind_impl<
-                        result_type,
-                        std::is_same<F_result_type,void>::value
-                    >::bind(data, std::forward<F>(f));
-            }
+
+            return bind_impl<result_type, std::is_void<F_result_type>::value>::
+                       bind(data, std::forward<F>(f));
         }
 
         template <typename F>
-        auto operator>>(F &&f) -> decltype(this->bind(std::forward<F>(f))) {
+        auto operator>>(F&& f) -> decltype(this->bind(std::forward<F>(f))) {
             return bind(std::forward<F>(f));
         }
 
         template <typename F>
-        auto operator>>(F &&f) const -> decltype(this->bind(std::forward<F>(f))) {
+        auto operator>>(F&& f) const -> decltype(this->bind(std::forward<F>(f))) {
             return bind(std::forward<F>(f));
         }
 
@@ -224,7 +208,7 @@ namespace detail {
         template <typename R, bool F_void_return>
         struct bind_impl {
             template <typename DT,typename F>
-            static R bind(DT &d,F &&f) {
+            static R bind(DT& d,F&& f) {
                 return R(d.apply(std::forward<F>(f)));
             }
         };
@@ -232,17 +216,22 @@ namespace detail {
         template <typename R>
         struct bind_impl<R,true> {
             template <typename DT,typename F>
-            static R bind(DT &d,F &&f) {
+            static R bind(DT& d,F&& f) {
                 d.apply(std::forward<F>(f));
                 return R(true);
             }
         };
     };
-}
+
+    // type utilities
+    template <typename T>
+    using enable_unless_optional_t = enable_if_t<!is_optional<T>::value>;
+
+} // namespace detail
 
 template <typename X>
 struct optional: detail::optional_base<X> {
-    using base=detail::optional_base<X>;
+    using base = detail::optional_base<X>;
     using base::set;
     using base::ref;
     using base::reset;
@@ -251,63 +240,54 @@ struct optional: detail::optional_base<X> {
     optional(): base() {}
     optional(nothing_t): base() {}
 
-    // ... this makes it much easier to read
     template <
         typename Y = X,
-        typename = typename std::enable_if<std::is_copy_constructible<Y>::value>::type
-        // and this is how it would look with my style :
-      //typename = std::enable_if<std::is_copy_constructible<Y>()>
+        typename = enable_if_copy_constructible_t<Y>
     >
-    optional(const X &x)
-    :   base(true,x)
-    {}
-
-    // and out of curiosity, this is how it would have looked if the C++ standards
-    // folks had got it right the first time
+    optional(const X& x): base(true, x) {}
 
-    template <typename Y=X,typename = typename std::enable_if<std::is_move_constructible<Y>::value>::type>
-    optional(X &&x): base(true,std::move(x)) {}
+    template <
+        typename Y = X,
+        typename = enable_if_move_constructible_t<Y>
+    >
+    optional(X&& x): base(true, std::move(x)) {}
 
-    optional(const optional &ot): base(ot.set,ot.ref()) {}
+    optional(const optional& ot): base(ot.set, ot.ref()) {}
 
     template <typename T>
-    optional(const optional<T> &ot): base(ot.set,ot.ref()) {}
+    optional(const optional<T>& ot): base(ot.set, ot.ref()) {}
 
-    optional(optional &&ot): base(ot.set,std::move(ot.ref())) {}
+    optional(optional&& ot): base(ot.set, std::move(ot.ref())) {}
 
     template <typename T>
-    optional(optional<T> &&ot): base(ot.set,std::move(ot.ref())) {}
+    optional(optional<T>&& ot): base(ot.set, std::move(ot.ref())) {}
 
-    // constexpr yay!
-    //template <typename Y,typename = typename std::enable_if<!detail::is_optional<Y>::value>::type>
     template <
         typename Y,
-        typename = typename std::enable_if<!detail::is_optional<Y>()>::type
+        typename = detail::enable_unless_optional_t<Y>
     >
-    optional &operator=(Y &&y) {
+    optional& operator=(Y&& y) {
         if (set) {
-            ref()=std::forward<Y>(y);
+            ref() = std::forward<Y>(y);
         }
         else {
-            set=true;
+            set = true;
             data.construct(std::forward<Y>(y));
         }
         return *this;
     }
 
-    // small style point
-    //optional &operator=(const optional &o) {
-    optional& operator=(const optional &o) {
+    optional& operator=(const optional& o) {
         if (set) {
             if (o.set) {
-                ref()=o.ref();
+                ref() = o.ref();
             }
             else {
                 reset();
             }
         }
         else {
-            set=o.set;
+            set = o.set;
             if (set) {
                 data.construct(o.ref());
             }
@@ -315,54 +295,54 @@ struct optional: detail::optional_base<X> {
         return *this;
     }
 
-    // this is much clearer
-    // I line the closing template > like I would a curly brace
     template <
-        typename Y=X,
-        typename = typename
-            std::enable_if<
-                std::is_move_assignable<Y>::value &&
-                std::is_move_constructible<Y>::value
-            >::type
+        typename Y = X,
+        typename = typename std::enable_if<
+            std::is_move_assignable<Y>::value &&
+            std::is_move_constructible<Y>::value
+        >::type
     >
-    optional& operator=(optional &&o) {
-        // fix the {} !
+    optional& operator=(optional&& o) {
         if (set) {
-            if (o.set) ref()=std::move(o.ref());
+            if (o.set) {
+                ref() = std::move(o.ref());
+            }
             else reset();
         }
         else {
-            set=o.set;
-            if (set) data.construct(std::move(o.ref()));
+            set = o.set;
+            if (set) {
+                data.construct(std::move(o.ref()));
+            }
         }
         return *this;
     }
 };
 
 template <typename X>
-struct optional<X &>: detail::optional_base<X &> {
-    using base=detail::optional_base<X &>;
+struct optional<X&>: detail::optional_base<X&> {
+    using base=detail::optional_base<X&>;
     using base::set;
     using base::ref;
     using base::data;
 
     optional(): base() {}
     optional(nothing_t): base() {}
-    optional(X &x): base(true,x) {}
+    optional(X&x): base(true,x) {}
 
     template <typename T>
-    optional(optional<T &> &ot): base(ot.set,ot.ref()) {}
+    optional(optional<T&>& ot): base(ot.set,ot.ref()) {}
 
     template <typename Y,typename = typename std::enable_if<!detail::is_optional<Y>()>::type>
-    optional &operator=(Y &y) {
-        set=true;
-        ref()=y;
+    optional& operator=(Y& y) {
+        set = true;
+        ref() = y;
         return *this;
     }
 
     template <typename Y>
-    optional &operator=(optional<Y &> &o) {
-        set=o.set;
+    optional& operator=(optional<Y&>& o) {
+        set = o.set;
         data.construct(o);
         return *this;
     }
@@ -374,7 +354,7 @@ struct optional<X &>: detail::optional_base<X &> {
 
 template <>
 struct optional<void>: detail::optional_base<void> {
-    using base=detail::optional_base<void>;
+    using base = detail::optional_base<void>;
     using base::set;
 
     optional(): base() {}
@@ -383,19 +363,24 @@ struct optional<void>: detail::optional_base<void> {
     optional(T): base(true,true) {}
 
     template <typename T>
-    optional(const optional<T> &o): base(o.set,true) {}
+    optional(const optional<T>& o): base(o.set,true) {}
     
     template <typename T>
-    optional &operator=(T) { set=true; return *this; }
+    optional& operator=(T) {
+        set = true;
+        return *this;
+    }
 
     template <typename T>
-    optional &operator=(const optional<T> &o) { set=o.set; return *this; }
+    optional& operator=(const optional<T>& o) {
+        set = o.set;
+        return *this;
+    }
 
-    // override equality operators
     template <typename Y>
-    bool operator==(const Y &y) const { return false; }
+    bool operator==(const Y& y) const { return false; }
 
-    bool operator==(const optional<void> &o) const {
+    bool operator==(const optional<void>& o) const {
         return (set && o.set) || (!set && !o.set);
     }
 };
@@ -403,26 +388,26 @@ struct optional<void>: detail::optional_base<void> {
 
 template <typename A,typename B>
 typename std::enable_if<
-    detail::is_optional<A>() || detail::is_optional<B>(),
+    detail::is_optional<A>::value || detail::is_optional<B>::value,
     optional<
         typename std::common_type<
-            typename detail::wrapped_type<A>,
-            typename detail::wrapped_type<B>
+            detail::wrapped_type_t<A>,
+            detail::wrapped_type_t<B>
         >::type
     >
 >::type
-operator|(A &&a,B &&b) {
+operator|(A&& a,B&& b) {
     return a ? a : b;
 }
 
 template <typename A,typename B>
 typename std::enable_if<
-    detail::is_optional<A>() || detail::is_optional<B>(),
-    optional<detail::wrapped_type<B>>
+    detail::is_optional<A>::value || detail::is_optional<B>::value,
+    optional<detail::wrapped_type_t<B>>
 >::type
 operator&(A&& a,B&& b) {
-    using result_type=optional<detail::wrapped_type<B>>;
-    return a?b:result_type();
+    using result_type = optional<detail::wrapped_type_t<B>>;
+    return a ? b: result_type();
 }
 
 inline optional<void> provided(bool condition) {
@@ -430,7 +415,7 @@ inline optional<void> provided(bool condition) {
 }
 
 template <typename X>
-optional<X> just(X &&x) {
+optional<X> just(X&& x) {
     return optional<X>(std::forward<X>(x));
 }
 
diff --git a/src/util/uninitialized.hpp b/src/util/uninitialized.hpp
index f2449e41..846e46d5 100644
--- a/src/util/uninitialized.hpp
+++ b/src/util/uninitialized.hpp
@@ -5,13 +5,15 @@
  * The uninitialized<X> structure holds space for an item of
  * type X, leaving its construction or destruction to the user.
  * 
- * Specialisations for reference types X & and for the void type
+ * Specialisations for reference types X& and for the void type
  * allow for the handling of non-value types in a uniform manner.
  */
 
 #include <type_traits>
 #include <utility>
 
+#include "util/meta.hpp"
+
 namespace nest {
 namespace mc {
 namespace util {
@@ -22,47 +24,47 @@ namespace util {
 template <typename X>
 struct uninitialized {
 private:
-    typename std::aligned_storage<sizeof(X),alignof(X)>::type data;
+    typename std::aligned_storage<sizeof(X), alignof(X)>::type data;
 
 public:
-    using pointer_type=X *;
-    using const_pointer_type=const X *;
-    using reference_type=X &;
-    using const_reference_type=const X &;
+    using pointer_type = X*;
+    using const_pointer_type = const X*;
+    using reference_type = X&;
+    using const_reference_type = const X&;
 
-    pointer_type ptr() { return reinterpret_cast<X *>(&data); }
-    const_pointer_type cptr() const { return reinterpret_cast<const X *>(&data); }
+    pointer_type ptr() { return reinterpret_cast<X*>(&data); }
+    const_pointer_type cptr() const { return reinterpret_cast<const X*>(&data); }
 
-    reference_type ref() { return *reinterpret_cast<X *>(&data); }
-    const_reference_type cref() const { return *reinterpret_cast<const X *>(&data); }
+    reference_type ref() { return *reinterpret_cast<X*>(&data); }
+    const_reference_type cref() const { return *reinterpret_cast<const X*>(&data); }
 
     // Copy construct the value.
     template <
         typename Y = X,
-        typename = typename
-            std::enable_if< std::is_copy_constructible<Y>::value >::type
+        typename = enable_if_copy_constructible_t<Y>
     >
-    void construct(const X &x) {
+    void construct(const X& x) {
         new(&data) X(x);
     }
 
     // General constructor for X, forwarding arguments.
-    template <typename... Y,
-              typename =typename std::enable_if<std::is_constructible<X,Y...>::value>::type>
-    void construct(Y&& ...args) { new(&data) X(std::forward<Y>(args)...); }
+    template <
+        typename... Y,
+        typename = enable_if_constructible_t<X, Y...>
+    >
+    void construct(Y&& ...args) {
+        new(&data) X(std::forward<Y>(args)...);
+    }
 
     void destruct() { ptr()->~X(); }
 
     // Apply the one-parameter functor F to the value by reference.
     template <typename F>
-    typename std::result_of<F(reference_type)>::type
-    apply(F &&f) {
-        return f(ref());
-    }
+    result_of_t<F(reference_type)> apply(F&& f) { return f(ref()); }
 
     // Apply the one-parameter functor F to the value by const reference.
     template <typename F>
-    typename std::result_of<F(const_reference_type)>::type apply(F &&f) const { return f(cref()); }
+    result_of_t<F(const_reference_type)> apply(F&& f) const { return f(cref()); }
 };
 
 /* Maintains storage for a pointer of type X, representing
@@ -74,10 +76,10 @@ private:
     X *data;
 
 public:
-    using pointer_type=X *;
-    using const_pointer_type=const X *;
-    using reference_type=X &;
-    using const_reference_type=const X &;
+    using pointer_type = X*;
+    using const_pointer_type = const X*;
+    using reference_type = X&;
+    using const_reference_type = const X&;
 
     pointer_type ptr() { return data; }
     const_pointer_type cptr() const { return data; }
@@ -85,15 +87,20 @@ public:
     reference_type ref() { return *data; }
     const_reference_type cref() const { return *data; }
 
-    void construct(X &x) { data=&x; }
+    void construct(X& x) { data = &x; }
     void destruct() {}
 
     // Apply the one-parameter functor F to the value by reference.
     template <typename F>
-    typename std::result_of<F(reference_type)>::type apply(F &&f) { return f(ref()); }
+    result_of_t<F(reference_type)> apply(F&& f) {
+        return f(ref());
+    }
+
     // Apply the one-parameter functor F to the value by const reference.
     template <typename F>
-    typename std::result_of<F(const_reference_type)>::type apply(F &&f) const { return f(cref()); }
+    result_of_t<F(const_reference_type)> apply(F&& f) const {
+        return f(cref());
+    }
 };
 
 /* Wrap a void type in an uninitialized template.
@@ -102,10 +109,10 @@ public:
  */
 template <>
 struct uninitialized<void> {
-    using pointer_type=void *;
-    using const_pointer_type=const void *;
-    using reference_type=void;
-    using const_reference_type=void;
+    using pointer_type = void*;
+    using const_pointer_type = const void*;
+    using reference_type = void;
+    using const_reference_type = void;
 
     pointer_type ptr() { return nullptr; }
     const_pointer_type cptr() const { return nullptr; }
@@ -120,29 +127,9 @@ struct uninitialized<void> {
 
     // Equivalent to f()
     template <typename F>
-    typename std::result_of<F()>::type apply(F &&f) const { return f(); }
+    result_of_t<F()> apply(F&& f) const { return f(); }
 };
 
-// proposed change...
-// is this too much?
-template <typename...>
-struct uninitialized_can_construct_: std::false_type {};
-
-template <typename X,typename... Y>
-struct uninitialized_can_construct_<X,Y...>: std::integral_constant<bool,std::is_constructible<X,Y...>::value> {};
-
-template <typename X,typename Y>
-struct uninitialized_can_construct_<X &,Y>: std::integral_constant<bool,std::is_convertible<X &,Y>::value> {};
-
-template <typename... Y>
-struct uninitialized_can_construct_<void,Y...>: std::true_type {};
-
-
-template <typename... X>
-constexpr bool uninitialized_can_construct() {
-    return uninitialized_can_construct_<X...>::value;
-}
-
 } // namespace util
 } // namespace mc
 } // namespace nest
-- 
GitLab