From 17f331bb579967fd8709444f08be6a8a50344607 Mon Sep 17 00:00:00 2001 From: Daniel Arndt Date: Sun, 6 Oct 2019 21:36:59 -0400 Subject: [PATCH] Remove std::bind from examples --- examples/step-12/step-12.cc | 4 +- examples/step-13/step-13.cc | 87 +++++++++------------------------- examples/step-14/step-14.cc | 41 ++++++++-------- examples/step-27/step-27.cc | 6 +-- examples/step-32/step-32.cc | 93 ++++++++++++++++++------------------- examples/step-44/step-44.cc | 44 +++++++++--------- examples/step-49/step-49.cc | 3 +- examples/step-51/step-51.cc | 21 +++++---- 8 files changed, 127 insertions(+), 172 deletions(-) diff --git a/examples/step-12/step-12.cc b/examples/step-12/step-12.cc index 8aac1461b7..5c02885ecd 100644 --- a/examples/step-12/step-12.cc +++ b/examples/step-12/step-12.cc @@ -203,7 +203,7 @@ namespace Step12 // pointers to these functions to the MeshWorker framework. If, however, // these functions would want to access member variables (or needed // additional arguments beyond the ones specified below), we could use the - // facilities of boost::bind (or std::bind, respectively) to provide the + // facilities of lambda functions to provide the // MeshWorker framework with objects that act as if they had the required // number and types of arguments, but have in fact other arguments already // bound. @@ -312,7 +312,7 @@ namespace Step12 // integrator class are not actually function pointers. Rather, they are // objects that can be called like functions with a certain number of // arguments. Consequently, we could also pass objects with appropriate - // operator() implementations here, or the result of std::bind if the local + // operator() implementations here, or lambda functions if the local // integrators were, for example, non-static member functions. MeshWorker::loop rhs_task = Threads::new_task(&Solver::assemble_rhs, *this, linear_system.rhs); - WorkStream::run(dof_handler.begin_active(), - dof_handler.end(), - std::bind(&Solver::local_assemble_matrix, - this, - std::placeholders::_1, - std::placeholders::_2, - std::placeholders::_3), - std::bind(&Solver::copy_local_to_global, - this, - std::placeholders::_1, - std::ref(linear_system)), - AssemblyScratchData(*fe, *quadrature), - AssemblyCopyData()); + WorkStream::run( + dof_handler.begin_active(), + dof_handler.end(), + [this](const typename DoFHandler::active_cell_iterator &cell, + AssemblyScratchData &scratch_data, + AssemblyCopyData & copy_data) { + this->local_assemble_matrix(cell, scratch_data, copy_data); + }, + [this, &linear_system](const AssemblyCopyData ©_data) { + this->copy_local_to_global(copy_data, linear_system); + }, + AssemblyScratchData(*fe, *quadrature), + AssemblyCopyData()); linear_system.hanging_node_constraints.condense(linear_system.matrix); - // The syntax above using std::bind requires + // The syntax above using lambda functions requires // some explanation. There are multiple version of // WorkStream::run that expect different arguments. In step-9, // we used one version that took a pair of iterators, a pair of @@ -783,58 +783,15 @@ namespace Step13 // function that just takes function objects -- objects that // have an operator() and that consequently can be // called like functions, whatever they really represent. The - // typical way to generate such function objects is using - // std::bind (or, if the compiler is too old, a - // replacement for it, which we generically call - // std::bind) which takes a pointer to a - // (member) function and then binds individual arguments - // to fixed values. For example, you can create a function that - // takes an iterator, a scratch object and a copy object by - // taking the address of a member function and binding the - // (implicit) argument to the object on which it is to work to - // *this. This is what we do in the first call - // above. In the second call, we need to create a function - // object that takes a copy object, and we do so by taking the - // address of a member function that takes an implicit pointer - // to *this, a reference to a copy object, and a - // reference to a linear system, and binding the first and third - // of these, leaving something that has only one open argument - // that can then be filled by WorkStream::run(). + // typical way to generate such function objects is using a + // lambda + // function that wraps the function call including the individual + // arguments with fixed values. The fixed values are passed into the + // lambda function using the capture list + // ([...]). All the other arguments the wrapped function requires and are + // part of the outer function signature are specified as regular function + // parameters in the lambda function. // - // There remains the question of what the - // std::placeholders::_1, std::placeholders::_2, - // etc., mean. (These arguments are called placeholders.) The idea - // of using std::bind in the first of the two cases above is - // that it produces an object that can be called with three arguments. But - // how are the three arguments the function object is being called with - // going to be distributed to the four arguments - // local_assemble_matrix() (including the implicit - // this pointer)? As specified, the first argument - // given to the function object will become the first argument - // given to local_assemble_matrix(), the second the - // second, etc. This is trivial here, but allows for interesting - // games in other circumstances. Consider, for example, having a - // function void f(double x, double y). Then, - // creating a variable p of type - // std::function@ and - // initializing p=std::bind(&f, std::placeholders::_2, - // std::placeholders::_1) then calling p(1,2) will - // result in calling f(2,1). - // - // @note An alternative to using std::bind is to use C++'s - // version of lambda - // functions. In essence, a lambda function is a function without a - // name that is defined right at the one place where it is going to be - // used -- i.e., where we pass the third and fourth argument to - // WorkStream::run. The functions one would define in these locations - // would take 3 and 1 arguments, respectively, and all they do is call - // Solver::local_assemble_matrix and - // Solver::copy_local_to_global with the required number of - // arguments, utilizing what the lambda function has gotten as arguments - // itself. We won't show the syntax this would require since it is no - // less confusing than the one used above. - // At this point, we have assembled the matrix and condensed // it. The right hand side may or may not have been completely // assembled, but we would like to condense the right hand side diff --git a/examples/step-14/step-14.cc b/examples/step-14/step-14.cc index 93b656cd39..2db1c83855 100644 --- a/examples/step-14/step-14.cc +++ b/examples/step-14/step-14.cc @@ -522,19 +522,19 @@ namespace Step14 Threads::Task<> rhs_task = Threads::new_task(&Solver::assemble_rhs, *this, linear_system.rhs); - WorkStream::run(dof_handler.begin_active(), - dof_handler.end(), - std::bind(&Solver::local_assemble_matrix, - this, - std::placeholders::_1, - std::placeholders::_2, - std::placeholders::_3), - std::bind(&Solver::copy_local_to_global, - this, - std::placeholders::_1, - std::ref(linear_system)), - AssemblyScratchData(*fe, *quadrature), - AssemblyCopyData()); + WorkStream::run( + dof_handler.begin_active(), + dof_handler.end(), + [this](const typename DoFHandler::active_cell_iterator &cell, + AssemblyScratchData &scratch_data, + AssemblyCopyData & copy_data) { + this->local_assemble_matrix(cell, scratch_data, copy_data); + }, + [this, &linear_system](const AssemblyCopyData ©_data) { + this->copy_local_to_global(copy_data, linear_system); + }, + AssemblyScratchData(*fe, *quadrature), + AssemblyCopyData()); linear_system.hanging_node_constraints.condense(linear_system.matrix); std::map boundary_value_map; @@ -2193,13 +2193,14 @@ namespace Step14 WorkStream::run( DualSolver::dof_handler.begin_active(), DualSolver::dof_handler.end(), - std::bind(&WeightedResidual::estimate_on_one_cell, - this, - std::placeholders::_1, - std::placeholders::_2, - std::placeholders::_3, - std::ref(error_indicators), - std::ref(face_integrals)), + [this, + &error_indicators, + &face_integrals](const active_cell_iterator & cell, + WeightedResidualScratchData &scratch_data, + WeightedResidualCopyData & copy_data) { + this->estimate_on_one_cell( + cell, scratch_data, copy_data, error_indicators, face_integrals); + }, std::function(), WeightedResidualScratchData(*DualSolver::fe, *DualSolver::quadrature, diff --git a/examples/step-27/step-27.cc b/examples/step-27/step-27.cc index f96e240123..9185c2d526 100644 --- a/examples/step-27/step-27.cc +++ b/examples/step-27/step-27.cc @@ -691,9 +691,9 @@ namespace Step27 std::pair, std::vector> res = FESeries::process_coefficients( fourier_coefficients, - std::bind(&LaplaceProblem::predicate, - this, - std::placeholders::_1), + [this](const TableIndices &indices) { + return this->predicate(indices); + }, VectorTools::Linfty_norm); Assert(res.first.size() == res.second.size(), ExcInternalError()); diff --git a/examples/step-32/step-32.cc b/examples/step-32/step-32.cc index 4ddf98af17..b72c40fb18 100644 --- a/examples/step-32/step-32.cc +++ b/examples/step-32/step-32.cc @@ -2106,19 +2106,17 @@ namespace Step32 // specific signatures: three arguments in the first and one // argument in the latter case (see the documentation of the // WorkStream::run function for the meaning of these arguments). - // Note how we use the construct std::bind to + // Note how we use a lambda functions to // create a function object that satisfies this requirement. It uses - // placeholders std::placeholders::_1, std::placeholders::_2, - // std::placeholders::_3 for the local assembly function that specify - // cell, scratch data, and copy data, as well as the placeholder - // std::placeholders::_1 for the copy function that expects the - // data to be written into the global matrix (for placeholder - // arguments, also see the discussion in step-13's - // assemble_linear_system() function). On the other + // function arguments for the local assembly function that specify + // cell, scratch data, and copy data, as well as function argument + // for the copy function that expects the + // data to be written into the global matrix (also see the discussion in + // step-13's assemble_linear_system() function). On the other // hand, the implicit zeroth argument of member functions (namely // the this pointer of the object on which that member // function is to operate on) is bound to the - // this pointer of the current function. The + // this pointer of the current function and is captured. The // WorkStream::run function, as a consequence, does not need to know // anything about the object these functions work on. // @@ -2150,16 +2148,14 @@ namespace Step32 CellFilter(IteratorFilters::LocallyOwnedCell(), stokes_dof_handler.begin_active()), CellFilter(IteratorFilters::LocallyOwnedCell(), stokes_dof_handler.end()), - std::bind( - &BoussinesqFlowProblem::local_assemble_stokes_preconditioner, - this, - std::placeholders::_1, - std::placeholders::_2, - std::placeholders::_3), - std::bind( - &BoussinesqFlowProblem::copy_local_to_global_stokes_preconditioner, - this, - std::placeholders::_1), + [this](const typename DoFHandler::active_cell_iterator &cell, + Assembly::Scratch::StokesPreconditioner & scratch, + Assembly::CopyData::StokesPreconditioner & data) { + this->local_assemble_stokes_preconditioner(cell, scratch, data); + }, + [this](const Assembly::CopyData::StokesPreconditioner &data) { + this->copy_local_to_global_stokes_preconditioner(data); + }, Assembly::Scratch::StokesPreconditioner(stokes_fe, quadrature_formula, mapping, @@ -2339,14 +2335,14 @@ namespace Step32 CellFilter(IteratorFilters::LocallyOwnedCell(), stokes_dof_handler.begin_active()), CellFilter(IteratorFilters::LocallyOwnedCell(), stokes_dof_handler.end()), - std::bind(&BoussinesqFlowProblem::local_assemble_stokes_system, - this, - std::placeholders::_1, - std::placeholders::_2, - std::placeholders::_3), - std::bind(&BoussinesqFlowProblem::copy_local_to_global_stokes_system, - this, - std::placeholders::_1), + [this](const typename DoFHandler::active_cell_iterator &cell, + Assembly::Scratch::StokesSystem & scratch, + Assembly::CopyData::StokesSystem & data) { + this->local_assemble_stokes_system(cell, scratch, data); + }, + [this](const Assembly::CopyData::StokesSystem &data) { + this->copy_local_to_global_stokes_system(data); + }, Assembly::Scratch::StokesSystem( stokes_fe, mapping, @@ -2453,15 +2449,14 @@ namespace Step32 temperature_dof_handler.begin_active()), CellFilter(IteratorFilters::LocallyOwnedCell(), temperature_dof_handler.end()), - std::bind(&BoussinesqFlowProblem::local_assemble_temperature_matrix, - this, - std::placeholders::_1, - std::placeholders::_2, - std::placeholders::_3), - std::bind( - &BoussinesqFlowProblem::copy_local_to_global_temperature_matrix, - this, - std::placeholders::_1), + [this](const typename DoFHandler::active_cell_iterator &cell, + Assembly::Scratch::TemperatureMatrix & scratch, + Assembly::CopyData::TemperatureMatrix & data) { + this->local_assemble_temperature_matrix(cell, scratch, data); + }, + [this](const Assembly::CopyData::TemperatureMatrix &data) { + this->copy_local_to_global_temperature_matrix(data); + }, Assembly::Scratch::TemperatureMatrix(temperature_fe, mapping, quadrature_formula), @@ -2721,18 +2716,20 @@ namespace Step32 temperature_dof_handler.begin_active()), CellFilter(IteratorFilters::LocallyOwnedCell(), temperature_dof_handler.end()), - std::bind(&BoussinesqFlowProblem::local_assemble_temperature_rhs, - this, - global_T_range, - maximal_velocity, - global_entropy_variation, - std::placeholders::_1, - std::placeholders::_2, - std::placeholders::_3), - std::bind( - &BoussinesqFlowProblem::copy_local_to_global_temperature_rhs, - this, - std::placeholders::_1), + [this, global_T_range, maximal_velocity, global_entropy_variation]( + const typename DoFHandler::active_cell_iterator &cell, + Assembly::Scratch::TemperatureRHS & scratch, + Assembly::CopyData::TemperatureRHS & data) { + this->local_assemble_temperature_rhs(global_T_range, + maximal_velocity, + global_entropy_variation, + cell, + scratch, + data); + }, + [this](const Assembly::CopyData::TemperatureRHS &data) { + this->copy_local_to_global_temperature_rhs(data); + }, Assembly::Scratch::TemperatureRHS( temperature_fe, stokes_fe, mapping, quadrature_formula), Assembly::CopyData::TemperatureRHS(temperature_fe)); diff --git a/examples/step-44/step-44.cc b/examples/step-44/step-44.cc index 1c4e9b1a5f..aebee6b5c3 100644 --- a/examples/step-44/step-44.cc +++ b/examples/step-44/step-44.cc @@ -2049,17 +2049,16 @@ namespace Step44 // call to WorkStream because assemble_system_tangent_one_cell // is a constant function and copy_local_to_global_K is // non-constant. - WorkStream::run(dof_handler.active_cell_iterators(), - std::bind(&Solid::assemble_system_tangent_one_cell, - this, - std::placeholders::_1, - std::placeholders::_2, - std::placeholders::_3), - std::bind(&Solid::copy_local_to_global_K, - this, - std::placeholders::_1), - scratch_data, - per_task_data); + WorkStream::run( + dof_handler.active_cell_iterators(), + [this](const typename DoFHandler::active_cell_iterator &cell, + ScratchData_K & scratch, + PerTaskData_K & data) { + this->assemble_system_tangent_one_cell(cell, scratch, data); + }, + [this](const PerTaskData_K &data) { this->copy_local_to_global_K(data); }, + scratch_data, + per_task_data); timer.leave_subsection(); } @@ -2234,17 +2233,18 @@ namespace Step44 PerTaskData_RHS per_task_data(dofs_per_cell); ScratchData_RHS scratch_data(fe, qf_cell, uf_cell, qf_face, uf_face); - WorkStream::run(dof_handler.active_cell_iterators(), - std::bind(&Solid::assemble_system_rhs_one_cell, - this, - std::placeholders::_1, - std::placeholders::_2, - std::placeholders::_3), - std::bind(&Solid::copy_local_to_global_rhs, - this, - std::placeholders::_1), - scratch_data, - per_task_data); + WorkStream::run( + dof_handler.active_cell_iterators(), + [this](const typename DoFHandler::active_cell_iterator &cell, + ScratchData_RHS & scratch, + PerTaskData_RHS & data) { + this->assemble_system_rhs_one_cell(cell, scratch, data); + }, + [this](const PerTaskData_RHS &data) { + this->copy_local_to_global_rhs(data); + }, + scratch_data, + per_task_data); timer.leave_subsection(); } diff --git a/examples/step-49/step-49.cc b/examples/step-49/step-49.cc index a2bc128ffb..2ba3480bff 100644 --- a/examples/step-49/step-49.cc +++ b/examples/step-49/step-49.cc @@ -237,8 +237,7 @@ void grid_4() // the address of a function that takes a point and returns a point, an object // that has an operator() like the code below, or for example, a // std::function@(const Point@<2@>)@> object one can -// get via std::bind in more complex cases. Here we have a simple -// transformation and use the simplest method: a lambda function. +// get as a lambda function. Here we choose the latter option. void grid_5() { Triangulation<2> triangulation; diff --git a/examples/step-51/step-51.cc b/examples/step-51/step-51.cc index acf4475e49..269ef7ec13 100644 --- a/examples/step-51/step-51.cc +++ b/examples/step-51/step-51.cc @@ -1027,16 +1027,17 @@ namespace Step51 PostProcessScratchData scratch( fe_u_post, fe_local, quadrature_formula, local_flags, flags); - WorkStream::run(dof_handler_u_post.begin_active(), - dof_handler_u_post.end(), - std::bind(&HDG::postprocess_one_cell, - std::ref(*this), - std::placeholders::_1, - std::placeholders::_2, - std::placeholders::_3), - std::function(), - scratch, - 0U); + WorkStream::run( + dof_handler_u_post.begin_active(), + dof_handler_u_post.end(), + [this](const typename DoFHandler::active_cell_iterator &cell, + PostProcessScratchData & scratch, + unsigned int & data) { + this->postprocess_one_cell(cell, scratch, data); + }, + [](const unsigned int &) {}, + scratch, + 0U); } Vector difference_per_cell(triangulation.n_active_cells()); -- 2.39.5