Line data Source code
1 : /*
2 : * Copyright (c) 2016: G-CSC, Goethe University Frankfurt
3 : * Author: Sebastian Reiter
4 : *
5 : * This file is part of UG4.
6 : *
7 : * UG4 is free software: you can redistribute it and/or modify it under the
8 : * terms of the GNU Lesser General Public License version 3 (as published by the
9 : * Free Software Foundation) with the following additional attribution
10 : * requirements (according to LGPL/GPL v3 §7):
11 : *
12 : * (1) The following notice must be displayed in the Appropriate Legal Notices
13 : * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 : *
15 : * (2) The following notice must be displayed at a prominent place in the
16 : * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 : *
18 : * (3) The following bibliography is recommended for citation and must be
19 : * preserved in all covered files:
20 : * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 : * parallel geometric multigrid solver on hierarchically distributed grids.
22 : * Computing and visualization in science 16, 4 (2013), 151-164"
23 : * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 : * flexible software system for simulating pde based models on high performance
25 : * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 : *
27 : * This program is distributed in the hope that it will be useful,
28 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 : * GNU Lesser General Public License for more details.
31 : */
32 :
33 : #ifndef __H__UG_factory
34 : #define __H__UG_factory
35 :
36 : #include <type_traits> // for std::is_base_of
37 : #include <boost/mpl/for_each.hpp>
38 : #include <boost/mpl/vector.hpp>
39 : #include "../boost_serialization.h"
40 : #include "detail/register_type_pair_functor.h"
41 :
42 : namespace ug{
43 :
44 : namespace detail{
45 : namespace factory{
46 : /// used internally to construct derived classes of a given type
47 : template <class TBase, class TDerived>
48 0 : TBase* DerivedClassFactory ()
49 : {
50 0 : return new TDerived;
51 : }
52 : }
53 : }
54 :
55 :
56 : /// A factory class which creates instances given a class-name
57 : /** Given a base-class 'TBase' and an optional boost::mpl sequence of pairs of
58 : * derived classes and strings 'TPairSeq', the ug::Factory class allows for the
59 : * creation of instances ofderived classes given a name. Additionally to the
60 : * classes contained in 'TPairSeq', one may register derived classes at runtime
61 : * through the 'register_class' method.
62 : *
63 : * Besides creation of registered classes through the 'create' method,
64 : * one can iterate over all registered classes or obtain a registered class-name
65 : * given a pointer to the base class.
66 : *
67 : * \note This factory class is somewhat limited compared to e.g. to boost::factory and
68 : * is not meant as a replacement. It's main purpose is to allow iteration
69 : * over registered classes and to perform automatic registration through
70 : * a type list.
71 : */
72 : template <class TBase, class TPairSeq = boost::mpl::vector<> >
73 : class Factory
74 : {
75 : public:
76 0 : Factory()
77 : {
78 : detail::RegisterTypePairFunctor<Factory> func(this);
79 : boost::mpl::for_each<TPairSeq>(func);
80 0 : }
81 :
82 : SmartPtr<TBase> create(const std::string& className)
83 : {
84 0 : return create(className.c_str());
85 : }
86 :
87 0 : SmartPtr<TBase> create(const char* className)
88 : {
89 0 : return SmartPtr<TBase>(create_raw(className));
90 : }
91 :
92 : TBase* create_raw(const std::string& className)
93 : {
94 : return create_raw(className.c_str());
95 : }
96 :
97 0 : TBase* create_raw(const char* className)
98 : {
99 0 : typename class_map_t::iterator iclass = m_classMap.find(std::string(className));
100 0 : UG_COND_THROW(iclass == m_classMap.end(),
101 : "Unregistered class-name used in 'Factory::create_raw': " << className);
102 0 : return iclass->second.factory();
103 : }
104 :
105 : template <class TDerived>
106 0 : void register_class(const char* name)
107 : {
108 : // UG_LOG("registering derived class: " << className << std::endl);
109 : static_assert((std::is_base_of<TBase, TDerived>::value), "TDerived is not a subclass of TBase");
110 :
111 0 : std::string className(name);
112 :
113 0 : m_classMap[className] = ClassInfo(
114 : name,
115 : &detail::factory::DerivedClassFactory<TBase, TDerived>);
116 :
117 0 : std::string typeName(typeid(TDerived).name());
118 0 : m_classNameMap[typeName] = className;
119 :
120 0 : m_classNames.push_back(className);
121 0 : }
122 :
123 : size_t num_classes() const {return m_classNames.size();}
124 : const std::string& class_name(const size_t i) const {return m_classNames.at(i);}
125 0 : const std::string& class_name(const TBase& cls) const
126 : {
127 0 : std::string typeName = typeid(cls).name();
128 : class_name_map_t::const_iterator i = m_classNameMap.find(typeName);
129 0 : if(i != m_classNameMap.end())
130 0 : return i->second;
131 0 : static const std::string defaultName ("");
132 : return defaultName;
133 : }
134 :
135 : private:
136 : typedef TBase* (*factory_sig)();
137 :
138 : struct ClassInfo {
139 0 : ClassInfo () {}
140 : ClassInfo (const char* _name,
141 : factory_sig _factory) :
142 : name(_name),
143 : factory(_factory)
144 : {}
145 :
146 : const char* name;
147 : factory_sig factory;
148 : };
149 :
150 : typedef std::map<std::string, ClassInfo> class_map_t;
151 : typedef std::map<std::string, std::string> class_name_map_t;
152 : class_map_t m_classMap;///< contains ClassInfo objects accessible by class-name.
153 : class_name_map_t m_classNameMap;///< key: type-name, value: class-names
154 : std::vector<std::string> m_classNames;
155 : };
156 :
157 : }// end of namespace
158 :
159 : #endif //__H__UG_factory
|