From 36b74d6ee1625f32c969ea0dd9faa76c8fc9265d Mon Sep 17 00:00:00 2001 From: Daniel Arndt Date: Fri, 9 Feb 2018 23:32:41 +0100 Subject: [PATCH] Let FETools::get_fe_by_name return a std::unique_ptr --- include/deal.II/fe/fe_tools.h | 21 +- include/deal.II/fe/fe_tools.templates.h | 273 +++++++++++------------- source/fe/fe_tools.inst.in | 2 +- tests/bits/fe_tools_09.cc | 8 +- tests/bits/fe_tools_10.cc | 8 +- tests/bits/fe_tools_11.cc | 8 +- tests/fe/fe_tools_01.cc | 4 +- tests/fe/get_fe_by_name_01.cc | 4 +- 8 files changed, 139 insertions(+), 189 deletions(-) diff --git a/include/deal.II/fe/fe_tools.h b/include/deal.II/fe/fe_tools.h index f4017d89cc..4c2aabfc86 100644 --- a/include/deal.II/fe/fe_tools.h +++ b/include/deal.II/fe/fe_tools.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -83,7 +84,7 @@ namespace FETools /** * Create a FiniteElement and return a pointer to it. */ - virtual FiniteElement * + virtual std::unique_ptr > get (const unsigned int degree) const = 0; /** @@ -91,8 +92,9 @@ namespace FETools * implemented for FE_Q) and return a pointer to it. */ - virtual FiniteElement * + virtual std::unique_ptr > get (const Quadrature<1> &quad) const = 0; + /** * Virtual destructor doing nothing but making the compiler happy. */ @@ -117,14 +119,14 @@ namespace FETools /** * Create a FiniteElement and return a pointer to it. */ - virtual FiniteElement * + virtual std::unique_ptr > get (const unsigned int degree) const; /** * Create a FiniteElement from a quadrature formula (currently only * implemented for FE_Q) and return a pointer to it. */ - virtual FiniteElement * + virtual std::unique_ptr > get (const Quadrature<1> &quad) const; }; @@ -1211,9 +1213,8 @@ namespace FETools * If no finite element can be reconstructed from this string, an exception * of type @p FETools::ExcInvalidFEName is thrown. * - * The function returns a pointer to a newly create finite element. It is in - * the caller's responsibility to destroy the object pointed to at an - * appropriate later time. + * The function returns a std::unique_ptr to a newly created finite element + * meaning the caller obtains ownership over the returned object. * * Since the value of the template argument can't be deduced from the * (string) argument given to this function, you have to explicitly specify @@ -1226,7 +1227,7 @@ namespace FETools * one wants to get a codimension 1 finite element. */ template - FiniteElement * + std::unique_ptr > get_fe_by_name (const std::string &name); @@ -1391,10 +1392,10 @@ namespace FETools namespace FETools { template - FiniteElement * + std::unique_ptr > FEFactory::get (const unsigned int degree) const { - return new FE(degree); + return std_cxx14::make_unique(degree); } namespace Compositing diff --git a/include/deal.II/fe/fe_tools.templates.h b/include/deal.II/fe/fe_tools.templates.h index 41da17234b..5079e80a5c 100644 --- a/include/deal.II/fe/fe_tools.templates.h +++ b/include/deal.II/fe/fe_tools.templates.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -938,7 +939,7 @@ namespace FETools // Not implemented in the general case. template - FiniteElement * + std::unique_ptr > FEFactory::get (const Quadrature<1> &) const { Assert(false, ExcNotImplemented()); @@ -947,111 +948,111 @@ namespace FETools // Specializations for FE_Q. template <> - FiniteElement<1, 1> * + std::unique_ptr > FEFactory >::get (const Quadrature<1> &quad) const { - return new FE_Q<1>(quad); + return std_cxx14::make_unique>(quad); } template <> - FiniteElement<2, 2> * + std::unique_ptr > FEFactory >::get (const Quadrature<1> &quad) const { - return new FE_Q<2>(quad); + return std_cxx14::make_unique>(quad); } template <> - FiniteElement<3, 3> * + std::unique_ptr > FEFactory >::get (const Quadrature<1> &quad) const { - return new FE_Q<3>(quad); + return std_cxx14::make_unique>(quad); } // Specializations for FE_Q_DG0. template <> - FiniteElement<1, 1> * + std::unique_ptr > FEFactory >::get (const Quadrature<1> &quad) const { - return new FE_Q_DG0<1>(quad); + return std_cxx14::make_unique>(quad); } template <> - FiniteElement<2, 2> * + std::unique_ptr > FEFactory >::get (const Quadrature<1> &quad) const { - return new FE_Q_DG0<2>(quad); + return std_cxx14::make_unique>(quad); } template <> - FiniteElement<3, 3> * + std::unique_ptr > FEFactory >::get (const Quadrature<1> &quad) const { - return new FE_Q_DG0<3>(quad); + return std_cxx14::make_unique>(quad); } // Specializations for FE_Q_Bubbles. template <> - FiniteElement<1, 1> * + std::unique_ptr > FEFactory >::get (const Quadrature<1> &quad) const { - return new FE_Q_Bubbles<1>(quad); + return std_cxx14::make_unique>(quad); } template <> - FiniteElement<2, 2> * + std::unique_ptr > FEFactory >::get (const Quadrature<1> &quad) const { - return new FE_Q_Bubbles<2>(quad); + return std_cxx14::make_unique>(quad); } template <> - FiniteElement<3, 3> * + std::unique_ptr > FEFactory >::get (const Quadrature<1> &quad) const { - return new FE_Q_Bubbles<3>(quad); + return std_cxx14::make_unique>(quad); } // Specializations for FE_DGQArbitraryNodes. template <> - FiniteElement<1, 1> * + std::unique_ptr > FEFactory >::get (const Quadrature<1> &quad) const { - return new FE_DGQArbitraryNodes<1>(quad); + return std_cxx14::make_unique>(quad); } template <> - FiniteElement<1, 2> * + std::unique_ptr > FEFactory >::get (const Quadrature<1> &quad) const { - return new FE_DGQArbitraryNodes<1, 2>(quad); + return std_cxx14::make_unique>(quad); } template <> - FiniteElement<1, 3> * + std::unique_ptr > FEFactory >::get (const Quadrature<1> &quad) const { - return new FE_DGQArbitraryNodes<1, 3>(quad); + return std_cxx14::make_unique>(quad); } template <> - FiniteElement<2, 2> * + std::unique_ptr > FEFactory >::get (const Quadrature<1> &quad) const { - return new FE_DGQArbitraryNodes<2>(quad); + return std_cxx14::make_unique>(quad); } template <> - FiniteElement<2, 3> * + std::unique_ptr > FEFactory >::get (const Quadrature<1> &quad) const { - return new FE_DGQArbitraryNodes<2, 3>(quad); + return std_cxx14::make_unique>(quad); } template <> - FiniteElement<3, 3> * + std::unique_ptr > FEFactory >::get (const Quadrature<1> &quad) const { - return new FE_DGQArbitraryNodes<3>(quad); + return std_cxx14::make_unique>(quad); } } @@ -1065,9 +1066,9 @@ namespace template void - fill_no_codim_fe_names (std::map > &result) + fill_no_codim_fe_names (std::map > &result) { - typedef std::shared_ptr FEFactoryPointer; + typedef std::unique_ptr FEFactoryPointer; result["FE_Q_Hierarchical"] = FEFactoryPointer(new FETools::FEFactory >); @@ -1130,9 +1131,9 @@ namespace // nonzero codimension. template void - fill_codim_fe_names (std::map > &result) + fill_codim_fe_names (std::map > &result) { - typedef std::shared_ptr FEFactoryPointer; + typedef std::unique_ptr FEFactoryPointer; result["FE_Bernstein"] = FEFactoryPointer(new FETools::FEFactory >); @@ -1166,12 +1167,12 @@ namespace // by the functions above. std::vector > > > + std::unique_ptr > > > fill_default_map() { std::vector > > > + std::unique_ptr > > > result(4); for (unsigned int d=0; d<4; ++d) @@ -1211,7 +1212,7 @@ namespace // all entries of this vector are of different type, we store // pointers to generic objects and cast them when needed. - // We use a shared pointer to factory objects, to ensure that they + // We use a unique pointer to factory objects, to ensure that they // get deleted at the end of the program run and don't end up as // apparent memory leaks to programs like valgrind. @@ -1223,7 +1224,7 @@ namespace static std::vector > > > + std::unique_ptr > > > fe_name_map = fill_default_map(); } @@ -2293,7 +2294,7 @@ namespace FETools // Insert the normalized name into // the map fe_name_map[dim][spacedim][name] = - std::shared_ptr (factory); + std::unique_ptr (factory); } @@ -2306,10 +2307,10 @@ namespace FETools // have a unique interface. could be done // smarter? template - FiniteElement * + std::unique_ptr > get_fe_by_name_ext (std::string &name, const std::map > + std::unique_ptr > &fe_name_map) { // Extract the name of the @@ -2338,120 +2339,84 @@ namespace FETools // recursive calls if one of // these calls should throw // an exception - std::vector*> base_fes; + std::vector > > base_fes; std::vector base_multiplicities; - try + + // Now, just the [...] + // part should be left. + if (name.size() == 0 || name[0] != '[') + throw (std::string("Invalid first character in ") + name); + do { - // Now, just the [...] - // part should be left. - if (name.size() == 0 || name[0] != '[') - throw (std::string("Invalid first character in ") + name); - do + // Erase the + // leading '[' or '-' + name.erase(0,1); + // Now, the name of the + // first base element is + // first... Let's get it + base_fes.push_back (get_fe_by_name_ext (name, + fe_name_map)); + // next check whether + // FESystem placed a + // multiplicity after + // the element name + if (name[0] == '^') { - // Erase the - // leading '[' or '-' + // yes. Delete the '^' + // and read this + // multiplicity name.erase(0,1); - // Now, the name of the - // first base element is - // first... Let's get it - base_fes.push_back (get_fe_by_name_ext (name, - fe_name_map)); - // next check whether - // FESystem placed a - // multiplicity after - // the element name - if (name[0] == '^') - { - // yes. Delete the '^' - // and read this - // multiplicity - name.erase(0,1); - - const std::pair tmp - = Utilities::get_integer_at_position (name, 0); - name.erase(0, tmp.second); - // add to length, - // including the '^' - base_multiplicities.push_back (tmp.first); - } - else - // no, so - // multiplicity is - // 1 - base_multiplicities.push_back (1); - - // so that's it for - // this base - // element. base - // elements are - // separated by '-', - // and the list is - // terminated by ']', - // so loop while the - // next character is - // '-' - } - while (name[0] == '-'); - - // so we got to the end - // of the '-' separated - // list. make sure that - // we actually had a ']' - // there - if (name.size() == 0 || name[0] != ']') - throw (std::string("Invalid first character in ") + name); - name.erase(0,1); - // just one more sanity check - Assert ((base_fes.size() == base_multiplicities.size()) - && - (base_fes.size() > 0), - ExcInternalError()); - - // ok, apparently - // everything went ok. so - // generate the composed - // element - FiniteElement *system_element = nullptr; - - // uses new FESystem constructor - // which is independent of - // the number of FEs in the system - system_element = new FESystem(base_fes, base_multiplicities); - - // now we don't need the - // list of base elements - // any more - for (unsigned int i=0; i tmp + = Utilities::get_integer_at_position (name, 0); + name.erase(0, tmp.second); + // add to length, + // including the '^' + base_multiplicities.push_back (tmp.first); + } + else + // no, so + // multiplicity is + // 1 + base_multiplicities.push_back (1); + + // so that's it for + // this base + // element. base + // elements are + // separated by '-', + // and the list is + // terminated by ']', + // so loop while the + // next character is + // '-' } - catch (...) - { - // ups, some exception - // was thrown. prevent a - // memory leak, and then - // pass on the exception - // to the caller - for (unsigned int i=0; i 0), + ExcInternalError()); + + // this is a workaround since the constructor for FESystem + // only accepts raw pointers. + std::vector *> raw_base_fes; + for (const auto &base_fe: base_fes) + raw_base_fes.push_back(base_fe.get()); + + // ok, apparently everything went ok. so generate the composed element. + // and return it. + return std_cxx14::make_unique > + (raw_base_fes, base_multiplicities); } else if (name_part == "FE_Nothing") { @@ -2556,7 +2521,7 @@ namespace FETools template - FiniteElement *get_fe_by_name (std::string &name) + std::unique_ptr >get_fe_by_name (std::string &name) { return get_fe_by_name_ext (name, fe_name_map[dim][spacedim]); } @@ -2569,13 +2534,13 @@ namespace FETools FiniteElement * get_fe_from_name (const std::string ¶meter_name) { - return get_fe_by_name (parameter_name); + return get_fe_by_name (parameter_name).release(); } template - FiniteElement * + std::unique_ptr > get_fe_by_name (const std::string ¶meter_name) { std::string name = Utilities::trim(parameter_name); @@ -2643,7 +2608,7 @@ namespace FETools try { - FiniteElement *fe = internal::get_fe_by_name (name); + auto fe = internal::get_fe_by_name (name); // Make sure the auxiliary function // ate up all characters of the name. diff --git a/source/fe/fe_tools.inst.in b/source/fe/fe_tools.inst.in index 30b1a8b698..e84477c400 100644 --- a/source/fe/fe_tools.inst.in +++ b/source/fe/fe_tools.inst.in @@ -130,7 +130,7 @@ for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS const FiniteElement &, FullMatrix &); - template FiniteElement * + template std::unique_ptr > get_fe_by_name (const std::string &); template diff --git a/tests/bits/fe_tools_09.cc b/tests/bits/fe_tools_09.cc index e598844729..54c54d4da7 100644 --- a/tests/bits/fe_tools_09.cc +++ b/tests/bits/fe_tools_09.cc @@ -29,8 +29,6 @@ void check_this (const FiniteElement &fe1, const FiniteElement &fe2) { - FiniteElement *p1, *p2; - // check that the name of the fe // and the name of the fe that we // re-create from this name are @@ -38,18 +36,16 @@ check_this (const FiniteElement &fe1, // pretty good indication that the // two FEs are actually the same deallog << fe1.get_name(); - p1 = FETools::get_fe_by_name (fe1.get_name()); + std::unique_ptr> p1 = FETools::get_fe_by_name (fe1.get_name()); AssertThrow (fe1.get_name() == p1->get_name(), ExcInternalError()); deallog << " ok" << std::endl; - delete p1; // same for fe2 deallog << fe2.get_name(); - p2 = FETools::get_fe_by_name (fe2.get_name()); + std::unique_ptr> p2 = FETools::get_fe_by_name (fe2.get_name()); AssertThrow (fe2.get_name() == p2->get_name(), ExcInternalError()); deallog << " ok" << std::endl; - delete p2; } diff --git a/tests/bits/fe_tools_10.cc b/tests/bits/fe_tools_10.cc index e4f7cfa3bc..84d5d14176 100644 --- a/tests/bits/fe_tools_10.cc +++ b/tests/bits/fe_tools_10.cc @@ -49,8 +49,6 @@ void check_this (const FiniteElement &fe1, const FiniteElement &fe2) { - FiniteElement *p1, *p2; - // check that the name of the fe // and the name of the fe that we // re-create from this name are @@ -58,18 +56,16 @@ check_this (const FiniteElement &fe1, // pretty good indication that the // two FEs are actually the same deallog << modify_name (fe1.get_name()); - p1 = FETools::get_fe_by_name (modify_name (fe1.get_name())); + std::unique_ptr > p1 = FETools::get_fe_by_name (modify_name (fe1.get_name())); AssertThrow (fe1.get_name() == p1->get_name(), ExcInternalError()); deallog << " ok" << std::endl; - delete p1; // same for fe2 deallog << modify_name (fe2.get_name()); - p2 = FETools::get_fe_by_name (modify_name (fe2.get_name())); + std::unique_ptr > p2 = FETools::get_fe_by_name (modify_name (fe2.get_name())); AssertThrow (fe2.get_name() == p2->get_name(), ExcInternalError()); deallog << " ok" << std::endl; - delete p2; } diff --git a/tests/bits/fe_tools_11.cc b/tests/bits/fe_tools_11.cc index 6298ef1450..4e2a6cab68 100644 --- a/tests/bits/fe_tools_11.cc +++ b/tests/bits/fe_tools_11.cc @@ -48,8 +48,6 @@ void check_this (const FiniteElement &fe1, const FiniteElement &fe2) { - FiniteElement *p1, *p2; - // check that the name of the fe // and the name of the fe that we // re-create from this name are @@ -57,18 +55,16 @@ check_this (const FiniteElement &fe1, // pretty good indication that the // two FEs are actually the same deallog << modify_name (fe1.get_name()); - p1 = FETools::get_fe_by_name (modify_name (fe1.get_name())); + std::unique_ptr> p1 = FETools::get_fe_by_name (modify_name (fe1.get_name())); AssertThrow (fe1.get_name() == p1->get_name(), ExcInternalError()); deallog << " ok" << std::endl; - delete p1; // same for fe2 deallog << modify_name (fe2.get_name()); - p2 = FETools::get_fe_by_name (modify_name (fe2.get_name())); + std::unique_ptr> p2 = FETools::get_fe_by_name (modify_name (fe2.get_name())); AssertThrow (fe2.get_name() == p2->get_name(), ExcInternalError()); deallog << " ok" << std::endl; - delete p2; } diff --git a/tests/fe/fe_tools_01.cc b/tests/fe/fe_tools_01.cc index adc93b5ab6..26afa85953 100644 --- a/tests/fe/fe_tools_01.cc +++ b/tests/fe/fe_tools_01.cc @@ -27,7 +27,7 @@ template void test_fe(const char *name) { - FiniteElement *fe = FETools::get_fe_by_name(std::string(name)); + std::unique_ptr > fe = FETools::get_fe_by_name(std::string(name)); deallog << fe->get_name() << std::endl << '\t' << fe->dofs_per_cell @@ -36,8 +36,6 @@ void test_fe(const char *name) << '\t' << fe->dofs_per_quad << '\t' << fe->dofs_per_hex << std::endl; - - delete fe; } diff --git a/tests/fe/get_fe_by_name_01.cc b/tests/fe/get_fe_by_name_01.cc index f61a491a48..25c80cdadb 100644 --- a/tests/fe/get_fe_by_name_01.cc +++ b/tests/fe/get_fe_by_name_01.cc @@ -35,13 +35,11 @@ public: { std::string name = myname; - FiniteElement *fe = FETools::get_fe_by_name(name); + std::unique_ptr >fe = FETools::get_fe_by_name(name); deallog << "Read " << name << std::endl; deallog << "Generated :" << std::endl; deallog << fe->get_name() << std::endl; - - delete fe; } -- 2.39.5