Line data Source code
1 : // The libMesh Finite Element Library. 2 : // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 : 4 : // This library is free software; you can redistribute it and/or 5 : // modify it under the terms of the GNU Lesser General Public 6 : // License as published by the Free Software Foundation; either 7 : // version 2.1 of the License, or (at your option) any later version. 8 : 9 : // This library is distributed in the hope that it will be useful, 10 : // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 : // Lesser General Public License for more details. 13 : 14 : // You should have received a copy of the GNU Lesser General Public 15 : // License along with this library; if not, write to the Free Software 16 : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 : 18 : 19 : 20 : #ifndef LIBMESH_FACTORY_H 21 : #define LIBMESH_FACTORY_H 22 : 23 : 24 : // Local includes 25 : #include "libmesh/libmesh_common.h" 26 : 27 : // C++ includes 28 : #include <cstddef> 29 : #include <map> 30 : #include <memory> // make_unique 31 : #include <string> 32 : 33 : namespace libMesh 34 : { 35 : 36 : 37 : 38 : /** 39 : * Factory class definition. 40 : * 41 : * \author Benjamin S. Kirk 42 : * \date 2002 43 : * \brief Handles name-based creation of objects. 44 : */ 45 : template <class Base> 46 : class Factory 47 : { 48 : protected: 49 : 50 : /** 51 : * Constructor. Takes the name to be mapped. 52 : */ 53 : Factory (const std::string & name); 54 : 55 : public: 56 : 57 : /** 58 : * Destructor. 59 : */ 60 3234 : virtual ~Factory () = default; 61 : 62 : /** 63 : * Builds an object of type Base identified by name. 64 : */ 65 : static std::unique_ptr<Base> build (const std::string & name); 66 : 67 : /** 68 : * Create a Base class. Force this to be implemented 69 : * later. 70 : */ 71 : virtual std::unique_ptr<Base> create () = 0; 72 : 73 : 74 : protected: 75 : 76 : /** 77 : * Map from a name to a Factory<Base> * pointer. 78 : */ 79 : static std::map<std::string, Factory<Base> *> & factory_map(); 80 : }; 81 : 82 : 83 : 84 : /** 85 : * Factory implementation class. 86 : */ 87 : template <class Derived, class Base> 88 : class FactoryImp: public Factory<Base> 89 : { 90 : public: 91 : 92 : /** 93 : * Constructor. Takes a name as input. 94 : */ 95 3234 : FactoryImp (const std::string & name) : Factory<Base>(name) { } 96 : 97 : /** 98 : * Destructor. Empty. 99 : */ 100 68328 : ~FactoryImp () = default; 101 : 102 : private: 103 : 104 : /** 105 : * \returns A new object of type Derived. 106 : */ 107 : virtual std::unique_ptr<Base> create () override; 108 : }; 109 : 110 : 111 : 112 : // ----------------------------------------------------- 113 : // Factory members 114 : template <class Base> 115 : inline 116 68328 : Factory<Base>::Factory (const std::string & name) 117 : { 118 : // Make sure we haven't already added this name 119 : // to the map 120 3234 : libmesh_assert (!factory_map().count(name)); 121 : 122 68328 : factory_map()[name] = this; 123 68328 : } 124 : 125 : 126 : 127 : template <class Base> 128 : inline 129 : std::unique_ptr<Base> Factory<Base>::build (const std::string & name) 130 : { 131 : // name not found in the map 132 : if (!factory_map().count(name)) 133 : { 134 : libMesh::err << "Tried to build an unknown type: " << name << std::endl; 135 : 136 : libMesh::err << "valid options are:" << std::endl; 137 : 138 : for (const auto & pr : factory_map()) 139 : libMesh::err << " " << pr.first << std::endl; 140 : 141 : libmesh_error_msg("Exiting..."); 142 : } 143 : 144 : Factory<Base> * f = factory_map()[name]; 145 : return std::unique_ptr<Base>(f->create()); 146 : } 147 : 148 : 149 : 150 : template <class Derived, class Base> 151 : inline 152 168 : std::unique_ptr<Base> FactoryImp<Derived,Base>::create () 153 : { 154 168 : return std::make_unique<Derived>(); 155 : } 156 : 157 : 158 : } // namespace libMesh 159 : 160 : #endif // LIBMESH_FACTORY_H