summaryrefslogtreecommitdiff
path: root/src/utilities/functorPtr.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/utilities/functorPtr.h')
-rw-r--r--src/utilities/functorPtr.h143
1 files changed, 143 insertions, 0 deletions
diff --git a/src/utilities/functorPtr.h b/src/utilities/functorPtr.h
new file mode 100644
index 0000000..438b358
--- /dev/null
+++ b/src/utilities/functorPtr.h
@@ -0,0 +1,143 @@
+/* This file is part of the OpenLB library
+ *
+ * Copyright (C) 2017 Adrian Kummerlaender
+ * E-mail contact: info@openlb.net
+ * The most recent release of OpenLB can be downloaded at
+ * <http://www.openlb.net/>
+ *
+ * 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, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef FUNCTOR_PTR_H
+#define FUNCTOR_PTR_H
+
+#include <memory>
+#include <type_traits>
+
+namespace olb {
+
+namespace util {
+
+/// Backport of C++17's std::void_t
+template<typename...>
+struct void_t {
+ using type = void;
+};
+
+/// Indicates existence of F::identity_functor_type typedef
+template<class F, class U = void>
+struct has_identity_functor : std::false_type { };
+/// Indicates existence of F::identity_functor_type typedef
+template<class F>
+struct has_identity_functor<F, typename void_t<typename F::identity_functor_type>::type> : std::true_type { };
+
+}
+
+/// Smart pointer for managing the various ways of passing functors around
+/**
+ * There is a rich set of functors that compose other functors by accepting
+ * them as constructor arguments. e.g. SuperLpNorm3D, SuperPlaneIntegralF3D
+ *
+ * Previously all of these functors only accepted other functors by reference
+ * which prevented e.g. the use case of accepting a std::unique_ptr to a
+ * indicator freshly created by SuperGeometry3D::getMaterialIndicator.
+ *
+ * This class hides the memory management required to support accepting either
+ * functor references, non-owning pointers or owning pointers in a single argument.
+ *
+ * Note that if this class is constructed by reference or raw pointer the caller
+ * is responsible for assuring that the passed functor is available for the full
+ * lifetime. This is not the case when constructed by a smart pointer.
+ **/
+template<typename F>
+class FunctorPtr {
+private:
+ /// Optional functor owner
+ std::unique_ptr<F> _ownF;
+ /// Optional shared functor
+ std::shared_ptr<F> _sharedF;
+ /// Pointer to the exposed functor
+ F* _f;
+ /// True iff FunctorPtr was constructed owning
+ const bool _owning;
+
+public:
+ /// Constructor for transparently accepting a functor reference
+ FunctorPtr(F& f);
+ /// Constructor for transparently accepting a non-owning functor pointer
+ FunctorPtr(F* f);
+ /// Constructor for transparently accepting a owning functor pointer
+ /**
+ * Equivalent to construction using a non-owning functor pointer
+ **/
+ FunctorPtr(const std::unique_ptr<F>& f);
+ /// Constructor for transparently taking ownership of a owning functor pointer
+ FunctorPtr(std::unique_ptr<F>&& f);
+ /// Constructor for transparently sharing ownership of a functor
+ FunctorPtr(std::shared_ptr<F> f);
+ /// Constructor for an empty instance
+ /**
+ * Equivalent to construction by nullptr.
+ **/
+ FunctorPtr();
+
+ /// Copy construction is disabled as it is incompatible with unique ownership
+ FunctorPtr(FunctorPtr&) = delete;
+ /// Move constructor
+ FunctorPtr(FunctorPtr&&) = default;
+
+ /// Perfect forwarding functor operator
+ template<typename... Args>
+ bool operator()(Args... args)
+ {
+ return _f->operator()(std::forward<Args>(args)...);
+ }
+
+ /// \returns reference to the exposed functor
+ typename std::add_lvalue_reference<F>::type operator*() const;
+ /// Enable pointer-like access to the exposed functor's members
+ typename std::add_pointer<F>::type operator->() const noexcept;
+
+ /// Indicates whether a functor instance is exposed
+ /**
+ * \returns true iff a functor is exposed
+ *
+ * This is useful for supporting optional functors in constructor interfaces
+ * by constructing FunctorPtr using a nullptr
+ **/
+ operator bool() const;
+
+ /// Indicates whether a functor instance is both exposed and owned
+ /**
+ * \returns true iff FunctorPtr took ownership of managed functor during construction
+ *
+ * It is not enough to check _ownF and _sharedF for non-nullptr contents as _sharedF
+ * is also used to store F::identity_functor_type instances created by toShared.
+ **/
+ bool isOwning() const;
+
+ /// Lifts managed functor reference for usage in std::shared_ptr<F> arithmetic
+ template<typename G = F>
+ auto toShared() -> typename std::enable_if< util::has_identity_functor<G>::value, std::shared_ptr<F>>::type;
+ /// Lifts managed functor reference for usage in std::shared_ptr<F> arithmetic (limited)
+ template<typename G = F>
+ auto toShared() -> typename std::enable_if<!util::has_identity_functor<G>::value, std::shared_ptr<F>>::type;
+
+};
+
+}
+
+#endif