Flow123d  last_with_con_2.0.0-4-g42e6930
factory.hh
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file factory.hh
15  * @brief
16  */
17 
18 #ifndef FIELD_RECORD_FACTORY_HH_
19 #define FIELD_RECORD_FACTORY_HH_
20 
21 #include <memory>
22 #include <string>
23 #include <map>
24 #include <functional>
25 #include <boost/functional/factory.hpp>
26 #include <boost/any.hpp>
27 
28 #include "system/exceptions.hh"
29 
30 
31 namespace Input {
32 
33 using namespace std;
34 
35 
36 TYPEDEF_ERR_INFO( EI_KeyName, const string);
37 TYPEDEF_ERR_INFO( EI_TypeName, const string);
38 DECLARE_EXCEPTION( ExcNotRegistredClass, << "Key " << EI_KeyName::val
39  << " isn't registered in factory for type " << EI_TypeName::val << "!");
40 
41 
42 /**
43  * @brief This class implements more general factory mechanism to construct classes.
44  *
45  * One factory allows constructing derived classes of one base class. This class is determined
46  * by template parameter Type and all descendants must implement constructor with same
47  * parameters (given by template parameter Arguments). This constructor is called by factory.
48  *
49  * All descendants must contain:
50  * 1. constructor with parameters given by Arguments
51  * 2. declaration of parent class as typedef with name FactoryBaseType
52  * 3. private static integer variable what is only for registration class to factory, this variable only allow
53  * to register class to factory and its implementation must call Factory::register_class what adds constructor
54  * of class to factory
55  *
56  * Simple example of usage:
57  @code
58  class SomeDescendant : public SomeBase
59  {
60  public:
61  /// typedef of parent class
62  typedef SomeBase FactoryBaseType;
63 
64  /// constructor
65  SomeDescendant() {}
66 
67  private:
68  /// registers class to factory
69  static const int reg;
70  }
71 
72  /// implementation of registration variable
73  const int SomeDescendant::reg =
74  Input::register_class< SomeDescendant >("SomeDescendant");
75  @endcode
76  *
77  * Factory allow to accept constructor with one or more parameters. In this case Factory is
78  * also templated by these parameters. For example Factory< SomeBase, int, double > accepts
79  * constructors with two parameters (int, double).
80  *
81  * If registered class is templated the following design have to be used:
82  @code
83  /// Example of class templated by integer parameter
84  template <int dimension>
85  class SomeDescendant : public SomeBase<dimension>
86  {
87  public:
88 
89  /// constructor
90  SomeDescendant(double time) {}
91  ...
92  }
93 
94  /// implementation of registration variable
95  const int SomeDescendant::reg =
96  Input::register_class< SomeDescendant<dimension>, double >("SomeDescendant");
97  @endcode
98  *
99  * Factory can be used in two ways:
100  * - through Factory::create method
101  * Example for constructor with one parameter:
102  @code
103  SomeBase * sb = Input::Factory< SomeBase, double >::instance()->create("SomeDescendant", 0.1);
104  @endcode
105  * - through AbstractRecord::factory method. This possibility can be used if base class has defined
106  * AbstractRecord and its descendants contain Record derived from this AbstractRecord.
107  * Example for same constructor:
108  @code
109  AbstractRecord a_rec = record.val<AbstractRecord>("problem");
110  SomeBase * sb = a_rec.factory< SomeBase, double>(0.25);
111  // If arguments types can be deduced (by compiler) from actual arguments one can even use:
112  SomeBase * sb = a_rec.factory< SomeBase >(0.25);
113  @endcode
114  *
115  * For correct functionality must be used two macros defined in global_defs.h:
116  * - FLOW123D_FORCE_LINK_IN_CHILD(x)
117  * - FLOW123D_FORCE_LINK_IN_PARENT(x)
118  * First is used in C source file of descendant class out of class methods, e.g.:
119  * FLOW123D_FORCE_LINK_IN_CHILD(gmsh)
120  * Second is used in C source file of parent class in any of class method with same parameter as in
121  * first used, e.g.:
122  * FLOW123D_FORCE_LINK_IN_PARENT(gmsh)
123  *
124  */
125 template <class Type, class... Arguments>
126 class Factory
127 {
128 public:
129  /// Get the single instance of the factory
130  static Factory * instance();
131 
132 
133  /// Register lambda function that calls default constructor of Type.
134  template <class Child>
135  static int register_class(string class_name);
136 
137 
138  /// create an instance of a registered class
139  shared_ptr<Type> const create(string name, Arguments... arguments) const;
140 
141 
142 private:
143  /// Forbid default constructor
145 
146  /// the registry of factory functions
148 
149 };
150 
151 
152 /**
153  * @brief Function allows simplified call of registering class to factory.
154  *
155  * It is used for declaration of registration variable.
156  * @see Factory
157  *
158  * Example of usage:
159  @code
160  const int SomeClass::reg =
161  Input::register_class< SomeClass >("SomeClass");
162  @endcode
163  */
164 template <class ChildType, class... Arguments>
165 int register_class(string class_name);
166 
167 
168 } // closing namespace Input
169 
170 // include implementation of templates and inline methods
171 #include "factory_impl.hh"
172 
173 #endif // FIELD_RECORD_FACTORY_HH_
DECLARE_EXCEPTION(ExcTypeMismatch,<< "Key:"<< EI_KeyName::qval<< ". Can not construct Iterator<T> with C++ type T="<< EI_CPPRequiredType::qval<< ";\n"<< "can not convert Type: "<< EI_InputType::qval<< " to: "<< EI_RequiredType::qval)
map< string, boost::any > factory_registry_
the registry of factory functions
Definition: factory.hh:147
int register_class(string class_name)
Function allows simplified call of registering class to factory.
Definition: factory_impl.hh:64
Factory()
Forbid default constructor.
Definition: factory.hh:144
TYPEDEF_ERR_INFO(EI_InputType, const string)
This class implements more general factory mechanism to construct classes.
Definition: factory.hh:126