$extrastylesheet
00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 00003 00004 // This library is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public 00006 // License as published by the Free Software Foundation; either 00007 // version 2.1 of the License, or (at your option) any later version. 00008 00009 // This library is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // Lesser General Public License for more details. 00013 00014 // You should have received a copy of the GNU Lesser General Public 00015 // License along with this library; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 00019 00020 #ifndef LIBMESH_FACTORY_H 00021 #define LIBMESH_FACTORY_H 00022 00023 00024 // Local includes 00025 #include "libmesh/libmesh_common.h" 00026 #include "libmesh/auto_ptr.h" 00027 00028 // C++ includes 00029 #include <cstddef> 00030 #include <map> 00031 #include <string> 00032 00033 namespace libMesh 00034 { 00035 00036 00037 00041 template <class Base> 00042 class Factory 00043 { 00044 protected: 00045 00049 Factory (const std::string& name); 00050 00051 public: 00052 00056 virtual ~Factory () {} 00057 00061 static UniquePtr<Base> build (const std::string& name); 00062 00067 virtual UniquePtr<Base> create () = 0; 00068 00069 00070 protected: 00071 00075 static std::map<std::string, Factory<Base>*>& factory_map(); 00076 }; 00077 00078 00079 00083 template <class Derived, class Base> 00084 class FactoryImp: public Factory<Base> 00085 { 00086 public: 00087 00091 FactoryImp (const std::string& name) : Factory<Base>(name) { } 00092 00096 ~FactoryImp () {} 00097 00098 private: 00099 00103 UniquePtr<Base> create (); 00104 00105 }; 00106 00107 00108 00109 // ----------------------------------------------------- 00110 // Factory members 00111 template <class Base> 00112 inline 00113 Factory<Base>::Factory (const std::string& name) 00114 { 00115 // Make sure we haven't already added this name 00116 // to the map 00117 libmesh_assert (!factory_map().count(name)); 00118 00119 factory_map()[name] = this; 00120 } 00121 00122 00123 00124 template <class Base> 00125 inline 00126 UniquePtr<Base> Factory<Base>::build (const std::string& name) 00127 { 00128 // name not found in the map 00129 if (!factory_map().count(name)) 00130 { 00131 libMesh::err << "Tried to build an unknown type: " << name << std::endl; 00132 00133 libMesh::err << "valid options are:" << std::endl; 00134 00135 for (typename std::map<std::string,Factory<Base>*>::const_iterator 00136 it = factory_map().begin(); it != factory_map().end(); ++it) 00137 libMesh::err << " " << it->first << std::endl; 00138 00139 libmesh_error_msg("Exiting..."); 00140 00141 // We'll never get here 00142 return UniquePtr<Base>(); 00143 } 00144 00145 Factory<Base> *f = factory_map()[name]; 00146 return UniquePtr<Base>(f->create()); 00147 } 00148 00149 00150 00151 // Note - this cannot be inlined! 00152 // template <class Base> 00153 // std::map<std::string, Factory<Base>*>& Factory<Base>::factory_map() 00154 // { 00155 // static std::map<std::string, Factory<Base>*> _factory_map; 00156 00157 // return _factory_map; 00158 // } 00159 00160 00161 00162 template <class Derived, class Base> 00163 inline 00164 UniquePtr<Base> FactoryImp<Derived,Base>::create () 00165 { 00166 return UniquePtr<Base>(new Derived); 00167 } 00168 00169 00170 } // namespace libMesh 00171 00172 #endif // LIBMESH_FACTORY_H