]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Replace std::bind in documentation 8892/head
authorDaniel Arndt <arndtd@ornl.gov>
Mon, 7 Oct 2019 02:40:09 +0000 (22:40 -0400)
committerDaniel Arndt <arndtd@ornl.gov>
Thu, 24 Oct 2019 03:36:22 +0000 (23:36 -0400)
include/deal.II/base/function.h
include/deal.II/base/mutable_bind.h
include/deal.II/base/parallel.h
include/deal.II/base/parameter_handler.h
include/deal.II/base/work_stream.h
include/deal.II/distributed/tria.h
include/deal.II/grid/filtered_iterator.h
include/deal.II/grid/tria.h
include/deal.II/lac/solver.h
include/deal.II/matrix_free/matrix_free.h
include/deal.II/numerics/time_dependent.h

index 051b55c79efb61a0081304293ba970a63833e65f..205f1bcf0d50b98e1f06dd3fbc4bf3c688e3766b 100644 (file)
@@ -649,10 +649,10 @@ protected:
  *
  * The class gains additional expressive power because the argument it takes
  * does not have to be a pointer to an actual function. Rather, it is a
- * function object, i.e., it can also be the result of call to std::bind (or
- * boost::bind) or some other object that can be called with a single
- * argument. For example, if you need a Function object that returns the norm
- * of a point, you could write it like so:
+ * function object, i.e., it can also be the result of a lambda function or some
+ * other object that can be called with a single argument. For
+ * example, if you need a Function object that returns the norm of a point, you
+ * could write it like so:
  * @code
  * template <int dim, typename RangeNumberType>
  * class Norm : public Function<dim, RangeNumberType>
@@ -702,7 +702,7 @@ protected:
  * or we could write it like so:
  * @code
  * ScalarFunctionFromFunctionObject<dim, RangeNumberType> my_distance_object(
- *   std::bind(&Point<dim>::distance, q, std::placeholders::_1));
+ *   [&q](const Point<dim> &p){return q.distance(p);});
  * @endcode
  * The savings in work to write this are apparent.
  *
index 8abbaf6d1a31bdc8b0a124c005ef652524bf0077..f2f888763cdc8454313cc6f38813ac2fb8f8abbb 100644 (file)
@@ -54,7 +54,7 @@ namespace Utilities
    * 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:
+   * wrap your function into a lambda function:
    *
    * @code
    *  void
@@ -67,10 +67,11 @@ namespace Utilities
    *  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),
+   *    [&p](const double &d,
+   *         const unsigned int i)
+   *    {
+   *      example_function(p, d, i);
+   *    },
    *    {}};
    *
    *  exp.parse_arguments("3.0 : 4");
index f68b6a9db4fb872702ba430373f116df3d8a3b9a..07fc76b72c5d590fae6aab535d2babbc5566c373 100644 (file)
@@ -398,11 +398,11 @@ namespace parallel
    *   {
    *     parallel::apply_to_subranges
    *        (0, A.n_rows(),
-   *         std::bind (&mat_vec_on_subranges,
-   *                    std::placeholders::_1, std::placeholders::_2,
-   *                    std::cref(A),
-   *                    std::cref(x),
-   *                    std::ref(y)),
+   *         [&](const unsigned int begin_row,
+   *             const unsigned int end_row)
+   *         {
+   *           mat_vec_on_subranges(begin_row, end_row, A, x, y);
+   *         },
    *         50);
    *   }
    *
@@ -418,14 +418,11 @@ namespace parallel
    *   }
    * @endcode
    *
-   * Note how we use the <code>std::bind</code> function to convert
+   * Note how we use the lambda function to convert
    * <code>mat_vec_on_subranges</code> from a function that takes 5 arguments
-   * to one taking 2 by binding the remaining arguments (the modifiers
-   * <code>std::ref</code> and <code>std::cref</code> make sure
-   * that the enclosed variables are actually passed by reference and constant
-   * reference, rather than by value). The resulting function object requires
-   * only two arguments, begin_row and end_row, with all other arguments
-   * fixed.
+   * to one taking 2 by binding the remaining arguments. The resulting function
+   * object requires only two arguments, `begin_row` and `end_row`, with all
+   * other arguments fixed.
    *
    * The code, if in single-thread mode, will call
    * <code>mat_vec_on_subranges</code> on the entire range
@@ -641,10 +638,11 @@ namespace parallel
    *      std::sqrt
    *       (parallel::accumulate_from_subranges<double>
    *        (0, A.n_rows(),
-   *         std::bind (&mat_norm_sqr_on_subranges,
-   *                     std::placeholders::_1, std::placeholders::_2,
-   *                     std::cref(A),
-   *                     std::cref(x)),
+   *         [&](const unsigned int begin_row,
+   *             const unsigned int end_row)
+   *         {
+   *           mat_vec_on_subranges(begin_row, end_row, A, x, y);
+   *         },
    *         50);
    *   }
    *
index 8cf22ea24c5902503101f49274ac3117370fda33..fdaaf0d61f358381553de192d919ce483c03c3ee 100644 (file)
@@ -346,7 +346,7 @@ class MultipleParameterLoop;
  * add_action() function.) Of course, in C++ one doesn't usually pass
  * around the address of a function, but an action can be a function-like
  * object (taking a string as argument) that results from calling
- * @p std::bind, or more conveniently, it can be a
+ * such as a
  * <a href="http://en.cppreference.com/w/cpp/language/lambda">lambda
  * function</a> that has the form
  * @code
index 1c7470f6c8bb51f5fdb8c1ad0c839b0ffe9f6d26..bb51de6613fd07e3f8ed7fbc82f3788e9d37ab56 100644 (file)
@@ -910,7 +910,8 @@ namespace WorkStream
    *
    * This function that can be used for worker and copier objects that are
    * either pointers to non-member functions or objects that allow to be
-   * called with an operator(), for example objects created by std::bind.
+   * called with an operator(), for example objects created by lambda functions
+   * or std::bind.
    *
    * The two data types <tt>ScratchData</tt> and <tt>CopyData</tt> need to
    * have a working copy constructor. <tt>ScratchData</tt> is only used in the
@@ -951,8 +952,11 @@ namespace WorkStream
    *
    * This function that can be used for worker and copier objects that are
    * either pointers to non-member functions or objects that allow to be
-   * called with an operator(), for example objects created by std::bind. If
-   * the copier is an empty function, it is ignored in the pipeline.
+   * called with an operator(), for example lambda functions
+   * or objects created by std::bind. If the copier is an empty function, it is
+   * ignored in the pipeline. (However, a lambda function with an empty body is
+   * *not* equivalent to an empty `std::function` object and will, consequently,
+   * not be ignored.
    *
    * The argument passed as @p end must be convertible to the same type as @p
    * begin, but doesn't have to be of the same type itself. This allows to
index 8376b466f60d37416236d9e2a184e524c8400748..04fbe84ab9953c735a9d9bbe24007ac8d09604a0 100644 (file)
@@ -170,18 +170,20 @@ namespace parallel
      *   ... create the coarse mesh ...
      *
      *   coarse_grid.signals.post_refinement.connect(
-     *     std::bind (&set_boundary_ids<dim>, std::ref(coarse_grid)));
+     *     [&coarse_grid](){
+     *       set_boundary_ids<dim>(coarse_grid);
+     *     });
      * }
      * @endcode
      *
-     * What the call to <code>std::bind</code> does is to produce an
-     * object that can be called like a function with no arguments. It does so
-     * by taking the address of a function that does, in fact, take an
-     * argument but permanently fix this one argument to a reference to the
-     * coarse grid triangulation. After each refinement step, the
+     * The object passed as argument to <code>connect</code> is an object
+     * that can be called like a function with no arguments. It does so by
+     * wrapping a function that does, in fact, take an argument but this one
+     * argument is stored as a reference to the coarse grid triangulation when
+     * the lambda function is created. After each refinement step, the
      * triangulation will then call the object so created which will in turn
-     * call <code>set_boundary_ids<dim></code> with the reference to the
-     * coarse grid as argument.
+     * call <code>set_boundary_ids<dim></code> with the reference to the coarse
+     * grid as argument.
      *
      * This approach can be generalized. In the example above, we have used a
      * global function that will be called. However, sometimes it is necessary
@@ -210,17 +212,17 @@ namespace parallel
      *   ... create the coarse mesh ...
      *
      *   coarse_grid.signals.post_refinement.connect(
-     *     std::bind (&MyGeometry<dim>::set_boundary_ids,
-     *                std::cref(*this),
-     *                std::ref(coarse_grid)));
+     *     [this, &coarse_grid]()
+     *     {
+     *       this->set_boundary_ids(coarse_grid);
+     *     });
      * }
      * @endcode
-     * Here, like any other member function, <code>set_boundary_ids</code>
-     * implicitly takes a pointer or reference to the object it belongs to as
-     * first argument. <code>std::bind</code> again creates an object that can
+     * The lambda function above again is an object that can
      * be called like a global function with no arguments, and this object in
-     * turn calls <code>set_boundary_ids</code> with a pointer to the current
-     * object and a reference to the triangulation to work on. Note that
+     * turn calls the current object's member function
+     * <code>set_boundary_ids</code> with a reference to the triangulation to
+     * work on. Note that
      * because the <code>create_coarse_mesh</code> function is declared as
      * <code>const</code>, it is necessary that the
      * <code>set_boundary_ids</code> function is also declared
index 14d0aa54e14b78ceabde6f03a015e93f678cb99b..4f8dd04e4b56fd99c902c81f08e4fb5650a7d7a0 100644 (file)
@@ -387,11 +387,11 @@ namespace IteratorFilters
  * @endcode
  * then
  * @code
- *   std::bind (&level_equal_to<active_cell_iterator>, std::placeholders::_1, 3)
+ *   [](const BIterator& c){ return level_equal_to<active_cell_iterator>(c, 3);}
  * @endcode
  * is another valid predicate (here: a function that returns true if either
  * the iterator is past the end or the level is equal to the second argument;
- * this second argument is bound to a fixed value using the @p std::bind
+ * this second argument is taken considered fixed when creating the lambda
  * function).
  *
  * Finally, classes can be predicates. The following class is one:
index fadbd3127bbac9296ea0e9ad1f412937a2bd3527..cc4c38c478a479c846413f6d0cb5cc86f50ce212 100644 (file)
@@ -1118,8 +1118,10 @@ namespace internal
  *       // triangulation that we want to be informed about mesh refinement
  *       previous_cell = current_cell;
  *       previous_cell->get_triangulation().signals.post_refinement.connect(
- *         std::bind (&FEValues<dim>::invalidate_previous_cell,
- *                    std::ref (*this)));
+ *         [this]()
+ *         {
+ *           this->invalidate_previous_cell();
+ *         });
  *     }
  *   else
  *    previous_cell = current_cell;
index 438959d2362290df4f99feda968c393cd0f7422d..89447402d5d126a5815cf8c32925f231c5cb7481 100644 (file)
@@ -206,18 +206,18 @@ class Vector;
  * In the language of signals, the functions called are called <i>slots</i>
  * and one can attach any number of slots to a signal. (The implementation of
  * signals and slots we use here is the one from the BOOST.signals2 library.)
- * A number of details may clarify what is happening underneath: - In reality,
- * the signal object does not store pointers to functions, but function
- * objects as slots. Each slot must conform to a particular signature: here,
- * it is an object that can be called with three arguments (the number of the
- * current linear iteration, the current residual, and the current iterate;
+ * A number of details may clarify what is happening underneath:
+ * - In reality, the signal object does not store pointers to functions, but
+ * function objects as slots. Each slot must conform to a particular signature:
+ * here, it is an object that can be called with three arguments (the number of
+ * the current linear iteration, the current residual, and the current iterate;
  * more specifics are discussed in the documentation of the connect()
  * function). A pointer to a function with this argument list satisfies the
  * requirements, but you can also pass a member function whose
- * <code>this</code> argument has been bound using the
- * <code>std::bind</code> mechanism (see the example below). - Each of
- * the slots will return a value that indicates whether the iteration should
- * continue, should stop because it has succeeded, or stop because it has
+ * <code>this</code> argument has been bound using a lambda function
+ * (see the example below).
+ * - Each of the slots will return a value that indicates whether the iteration
+ * should continue, should stop because it has succeeded, or stop because it has
  * failed. The return type of slots is therefore of type SolverControl::State.
  * The returned values from all of the slots will then have to be combined
  * before they are returned to the iterative solver that invoked the signal.
@@ -226,7 +226,8 @@ class Vector;
  * otherwise, if at least one slot returned SolverControl::iterate, then this
  * is going to be the return value of the signal; finally, only if all slots
  * return SolverControl::success will the signal's return value be
- * SolverControl::success. - It may of course be that a particular slot has
+ * SolverControl::success.
+ * - It may of course be that a particular slot has
  * been connected to the signal only to observe how the solution or a specific
  * part of it converges, but has no particular opinion on whether the
  * iteration should continue or not. In such cases, the slot should just
@@ -283,16 +284,17 @@ class Vector;
  *   SolverControl           solver_control (1000, 1e-12);
  *   SolverCG<>              solver (solver_control);
  *
- *   solver.connect (std::bind (&Step3::write_intermediate_solution,
- *                              this,
- *                              std::placeholders::_1,
- *                              std::placeholders::_2,
- *                              std::placeholders::_3));
+ *   solver.connect ([this](const unsigned int iteration,
+ *                          const double check_value,
+ *                          const Vector<double> *current_iterate){
+ *                     this->write_intermediate_solution(
+ *                       iteration, check_value, current_iterate);
+ *                   });
  *   solver.solve (system_matrix, solution, system_rhs,
  *                 PreconditionIdentity());
  * }
  * @endcode
- * The use of <code>std::bind</code> here ensures that we convert the
+ * The use of a lambda function here ensures that we convert the
  * member function with its three arguments plus the <code>this</code>
  * pointer, to a function that only takes three arguments, by fixing the
  * implicit <code>this</code> argument of the function to the
index eec8213bea8208d943d5b633c8626aa52ba1a452..276fa7d21acc26c0df639240230ef5708df6c20b 100644 (file)
@@ -741,7 +741,8 @@ public:
   /**
    * This is the second variant to run the loop over all cells, now providing
    * a function pointer to a member function of class `CLASS`. This method
-   * obviates the need to call std::bind to bind the class into the given
+   * obviates the need to define a lambda function or to call std::bind to bind
+   * the class into the given
    * function in case the local function needs to access data in the class
    * (i.e., it is a non-static member function).
    *
@@ -1054,7 +1055,8 @@ public:
    * member functions of class @p CLASS with the signature <code>operation
    * (const MatrixFree<dim,Number> &, OutVector &, InVector &,
    * std::pair<unsigned int,unsigned int>&)const</code>. This method obviates
-   * the need to call std::bind to bind the class into the given
+   * the need to define a lambda function or to call std::bind to bind
+   * the class into the given
    * function in case the local function needs to access data in the class
    * (i.e., it is a non-static member function).
    *
index 61c9a1289febbb9f4623712cc02a94915428961f..b5f9867fa66729779f1cc5f4367042f73d049dcd 100644 (file)
@@ -252,12 +252,12 @@ class Triangulation;
  *   void
  *   TimeDependent::solve_primal_problem ()
  *   {
- *     do_loop (std::bind(&TimeStepBase::init_for_primal_problem,
- *                        std::placeholders::_1),
- *              std::bind(&TimeStepBase::solve_primal_problem,
- *                        std::placeholders::_1),
- *              timestepping_data_primal,
- *              forward);
+ *     do_loop([](TimeStepBase *const time_step)
+ *               { time_step->init_for_primal_problem(); },
+ *             [](TimeStepBase *const time_step)
+ *               { time_step->solve_primal_problem(); },
+ *             timestepping_data_primal,
+ *             forward);
  *   }
  * @endcode
  * The latter function shows rather clear how most of the loops are invoked
@@ -276,23 +276,23 @@ class Triangulation;
  * look-back and the last one denotes in which direction the loop is to be
  * run.
  *
- * Using function pointers through the @p std::bind functions provided by the
- * <tt>C++</tt> standard library, it is possible to do neat tricks, like the
- * following, also taken from the wave program, in this case from the function
- * @p refine_grids:
+ * Using lambda functions it is possible to do neat tricks, like the
+ * following in this case from the function @p refine_grids:
  * @code
  *   ...
  *   compute the thresholds for refinement
  *   ...
  *
- *   do_loop (std::bind(&TimeStepBase_Tria<dim>::init_for_refinement,
- *                      std::placeholders::_1),
- *            std::bind(&TimeStepBase_Wave<dim>::refine_grid,
- *                      std::placeholders::_1,
- *                      TimeStepBase_Tria<dim>::RefinementData (
- *                        top_threshold, bottom_threshold)),
- *            TimeDependent::TimeSteppingData (0,1),
- *            TimeDependent::forward);
+ *   do_loop([](TimeStepBase_Tria<dim> *const time_step)
+ *             { time_step->init_for_refinement(); },
+ *           [=](TimeStepBase_Wave<dim> *const time_step)
+ *             {
+ *               time_step->solve_primal_problem(
+ *                 TimeStepBase_Tria<dim>::RefinementData (
+ *                   top_threshold, bottom_threshold)));
+ *             },
+ *           TimeDependent::TimeSteppingData (0,1),
+ *           TimeDependent::forward);
  * @endcode
  * TimeStepBase_Wave<dim>::refine_grid is a function taking an argument, unlike
  * all the other functions used above within the loops. However, in this special
@@ -535,10 +535,15 @@ public:
    * wake_up and @p sleep functions are called.
    *
    * To see how this function work, note that the function @p
-   * solve_primal_problem only consists of a call to <tt>do_loop
-   * (std::bind(&TimeStepBase::init_for_primal_problem, std::placeholders::_1),
-   * std::bind(&TimeStepBase::solve_primal_problem, std::placeholders::_1),
-   * timestepping_data_primal, forward);</tt>.
+   * solve_primal_problem only consists of the following call:
+   * @code
+   * do_loop([](TimeStepBase *const time_step)
+   *           { time_step->init_for_primal_problem(); },
+   *         [](TimeStepBase *const time_step)
+   *           { time_step->solve_primal_problem(); },
+   *         timestepping_data_primal,
+   *         forward);
+   * @endcode
    *
    * Note also, that the given class from which the two functions are taken
    * needs not necessarily be TimeStepBase, but it could also be a derived
@@ -549,10 +554,9 @@ public:
    * the TimeStepBase class.
    *
    * Instead of using the above form, you can equally well use
-   * <tt>std::bind(&X::unary_function, std::placeholders::_1, args...)</tt>
-   * which
-   * lets the @p do_loop function call the given function with the specified
-   * parameters.
+   * <tt>[args...](X *const x){x->unary_function(args...);}</tt>
+   * which lets the @p do_loop function call the given function with the
+   * specified parameters.
    */
   template <typename InitFunctionObject, typename LoopFunctionObject>
   void

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.