$extrastylesheet
factory.h
Go to the documentation of this file.
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