--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2019 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+#ifndef dealii_base_mutable_bind_h
+#define dealii_base_mutable_bind_h
+
+#include <deal.II/base/config.h>
+
+#include <deal.II/base/patterns.h>
+#include <deal.II/base/std_cxx14/utility.h>
+#include <deal.II/base/std_cxx17/tuple.h>
+
+#include <tuple>
+
+DEAL_II_NAMESPACE_OPEN
+
+namespace Utilities
+{
+ /**
+ * A mutable version of std::bind, that binds all arguments of a function
+ * pointer to a stored tuple, and allows you to update the tuple between
+ * calls.
+ *
+ * An example usage of this class is through the helper function
+ * mutable_bind() that creates a MutableBind object on the fly, based on its
+ * arguments:
+ *
+ * @code
+ * void my_function(const int &a, const double &b);
+ *
+ * auto bound = mutable_bind(my_function, 1, 2.0);
+ *
+ * bound(); // will execute my_function(1, 2.0);
+ *
+ * bound.set_arguments(2, 3.0);
+ * bound(); // will execute my_function(2, 3.0);
+ *
+ * bound.parse_arguments("3: 4.0");
+ * bound(); // will execute my_function(3, 4.0);
+ * @endcode
+ *
+ * The arguments are copied to the tuple, with their reference and const
+ * attributes removed. Only copy constructible objects are allowed as
+ * function arguments. If you need to keep some references around, you may
+ * wrap your function into a std::bind object:
+ *
+ * @code
+ * void
+ * example_function(const Point<2> &p,
+ * const double &d,
+ * const unsigned int i = 3) {
+ * ...
+ * };
+ *
+ * const Point<2> p(1, 2);
+ *
+ * Utilities::MutableBind<void, double, unsigned int> exp = {
+ * std::bind(example_function,
+ * std::cref(p),
+ * std::placeholders::_1,
+ * std::placeholders::_2),
+ * {}};
+ *
+ * exp.parse_arguments("3.0 : 4");
+ * exp(); // calls example_function(p, 3.0, 4);
+ * @endcode
+ *
+ * @authors Luca Heltai, Matthias Maier, 2019.
+ */
+ template <typename ReturnType, class... FunctionArgs>
+ class MutableBind
+ {
+ public:
+ /**
+ * An alias to the stored std::tuple type. Only copy constructible
+ * objects are allowed as tuple members.
+ */
+ using TupleType = std::tuple<typename std::remove_cv<
+ typename std::remove_reference<FunctionArgs>::type>::type...>;
+
+ /**
+ * Construct a MutableBind object specifying the function, and
+ * each arguments separately.
+ */
+ template <class FunctionType>
+ MutableBind(FunctionType function, FunctionArgs &&... arguments);
+
+ /**
+ * Construct a MutableBind object specifying the function, and
+ * the arguments as a tuple.
+ */
+ template <class FunctionType>
+ MutableBind(FunctionType function, TupleType &&arguments);
+
+ /**
+ * Construct a MutableBind object specifying only the function. By default,
+ * the arguments are left to their defult constructor values.
+ */
+ template <class FunctionType>
+ MutableBind(FunctionType function);
+
+ /**
+ * Call the original function, passing as arguments the elements of the
+ * tuple of bound arguments.
+ */
+ ReturnType
+ operator()() const;
+
+ /**
+ * Set the arguments to use in @p function, for next time
+ * operator()() is called, using move semantic.
+ */
+ void
+ set_arguments(TupleType &&arguments);
+
+ /**
+ * Set the arguments to use in @p function, for next time
+ * operator()() is called, using move semantic.
+ */
+ void
+ set_arguments(FunctionArgs &&... arguments);
+
+ /**
+ * Parse the arguments to use in @p function from a string, for next time
+ * operator()() is called.
+ *
+ * The conversion is performed using a user supplied Patterns::PatternBase
+ * object. By default, Patterns::Tools::Convert<TupleType>::to_pattern() is
+ * used to determine how to convert from @p value_string to a TupleType
+ * object.
+ *
+ * @param value_string The string to convert from
+ * @param pattern A unique pointer to the pattern to use when performing
+ * the conversion
+ */
+ void
+ parse_arguments(const std::string & value_string,
+ const std::unique_ptr<Patterns::PatternBase> &pattern =
+ Patterns::Tools::Convert<TupleType>::to_pattern());
+
+ private:
+ /**
+ * An std::function that stores the original function.
+ */
+ const std::function<ReturnType(FunctionArgs...)> function;
+
+ /**
+ * Currently stored arguments. These are forwarded to the function object
+ * above, when calling operator()().
+ */
+ TupleType arguments;
+ };
+
+
+
+ /**
+ * Create a MutableBind object from a function pointer and a list of
+ * arguments.
+ *
+ * An example usage is given by:
+ * @code
+ * void my_function(const int &a, const double &b);
+ *
+ * auto bound = mutable_bind(my_function, 1, 2.0);
+ *
+ * bound(); // will execute my_function(1, 2.0);
+ *
+ * bound.set_arguments(2, 3.0);
+ * bound(); // will execute my_function(2, 3.0);
+ *
+ * bound.parse_arguments("3: 4.0");
+ * bound(); // will execute my_function(3, 4.0);
+ * @endcode
+ *
+ * @authors Luca Heltai, Matthias Maier, 2019.
+ */
+ template <typename ReturnType, class... FunctionArgs>
+ MutableBind<ReturnType, FunctionArgs...>
+ mutable_bind(ReturnType (*function)(FunctionArgs...),
+ typename identity<FunctionArgs>::type &&... arguments);
+
+ /**
+ * Same as above, using a std::function object.
+ */
+ template <typename ReturnType, class... FunctionArgs>
+ MutableBind<ReturnType, FunctionArgs...>
+ mutable_bind(std::function<ReturnType(FunctionArgs...)>,
+ typename identity<FunctionArgs>::type &&... arguments);
+
+ /**
+ * Create a MutableBind object from a function pointer, with uninitialized
+ * arguments.
+ *
+ * Notice that if you do not call one of the MutableBind::set_arguments()
+ * methods, or the MutableBind::parse_arguments() function on the returned
+ * object, then the arguments passed to the function object will be
+ * initialized with the values coming from each of the arguments' default
+ * constructors.
+ */
+ template <typename ReturnType, class... FunctionArgs>
+ MutableBind<ReturnType, FunctionArgs...>
+ mutable_bind(ReturnType (*function)(FunctionArgs...));
+
+ /**
+ * Same as above, using a std::function object.
+ */
+ template <typename ReturnType, class... FunctionArgs>
+ MutableBind<ReturnType, FunctionArgs...>
+ mutable_bind(std::function<ReturnType(FunctionArgs...)>);
+
+
+
+#ifndef DOXYGEN
+ template <typename ReturnType, class... FunctionArgs>
+ template <class FunctionType>
+ MutableBind<ReturnType, FunctionArgs...>::MutableBind(
+ FunctionType function,
+ FunctionArgs &&... arguments)
+ : function(function)
+ , arguments(std::make_tuple(std::move(arguments)...)){};
+
+
+
+ template <typename ReturnType, class... FunctionArgs>
+ template <class FunctionType>
+ MutableBind<ReturnType, FunctionArgs...>::MutableBind(FunctionType function,
+ TupleType && arguments)
+ : function(function)
+ , arguments(std::move(arguments)){};
+
+
+
+ template <typename ReturnType, class... FunctionArgs>
+ template <class FunctionType>
+ MutableBind<ReturnType, FunctionArgs...>::MutableBind(FunctionType function)
+ : function(function){};
+
+
+
+ template <typename ReturnType, class... FunctionArgs>
+ ReturnType
+ MutableBind<ReturnType, FunctionArgs...>::operator()() const
+ {
+ return std_cxx17::apply(function, arguments);
+ }
+
+
+
+ template <typename ReturnType, class... FunctionArgs>
+ void
+ MutableBind<ReturnType, FunctionArgs...>::set_arguments(
+ FunctionArgs &&... args)
+ {
+ arguments = std::make_tuple(std::move(args)...);
+ }
+
+
+
+ template <typename ReturnType, class... FunctionArgs>
+ void
+ MutableBind<ReturnType, FunctionArgs...>::set_arguments(TupleType &&args)
+ {
+ arguments = std::move(args);
+ }
+
+
+
+ template <typename ReturnType, class... FunctionArgs>
+ void
+ MutableBind<ReturnType, FunctionArgs...>::parse_arguments(
+ const std::string & value_string,
+ const std::unique_ptr<Patterns::PatternBase> &pattern)
+ {
+ arguments =
+ Patterns::Tools::Convert<TupleType>::to_value(value_string, pattern);
+ }
+
+
+
+ template <typename ReturnType, class... FunctionArgs>
+ MutableBind<ReturnType, FunctionArgs...>
+ mutable_bind(ReturnType (*function)(FunctionArgs...),
+ typename identity<FunctionArgs>::type &&... arguments)
+ {
+ return MutableBind<ReturnType, FunctionArgs...>(function,
+ std::move(arguments)...);
+ };
+
+
+
+ template <typename ReturnType, class... FunctionArgs>
+ MutableBind<ReturnType, FunctionArgs...>
+ mutable_bind(ReturnType (*function)(FunctionArgs...))
+ {
+ return MutableBind<ReturnType, FunctionArgs...>(function);
+ }
+
+
+
+ template <typename ReturnType, class... FunctionArgs>
+ MutableBind<ReturnType, FunctionArgs...>
+ mutable_bind(std::function<ReturnType(FunctionArgs...)> function,
+ typename identity<FunctionArgs>::type &&... arguments)
+ {
+ return MutableBind<ReturnType, FunctionArgs...>(function,
+ std::move(arguments)...);
+ }
+
+
+
+ template <typename ReturnType, class... FunctionArgs>
+ MutableBind<ReturnType, FunctionArgs...>
+ mutable_bind(std::function<ReturnType(FunctionArgs...)> function)
+ {
+ return MutableBind<ReturnType, FunctionArgs...>(function);
+ }
+#endif
+} // namespace Utilities
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif