Omnidome
Fulldome Mapping Software Toolkit
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
factory.hpp
Go to the documentation of this file.
1 /* Copyright (c) 2014-2015 "Omnidome" by cr8tr
2  * Dome Mapping Projection Software (http://omnido.me).
3  * Omnidome was created by Michael Winkelmann aka Wilston Oreo (@WilstonOreo)
4  *
5  * This file is part of Omnidome.
6  *
7  * Omnidome is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as
9  * published by the Free Software Foundation, either version 3 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU Affero General Public License for more details.
16  * You should have received a copy of the GNU Affero General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef BOOSTX_FACTORY_HPP_
21 #define BOOSTX_FACTORY_HPP_
22 
23 #include <unordered_map>
24 #include <functional>
25 #include <type_traits>
26 
27 namespace boostx
28 {
29  template<typename T, typename REGISTRY, typename...ARGS>
30  struct registrar;
31 
32  /**@brief The central factory class.
33  * @tparam INTERFACE Typename of the abstract interface
34  * @tparam TYPEINFO Template template parameter for the typeinfo
35  * @tparam ...ARGS Template parameter which comply to the constructor signature of the interface
36  */
37  template<typename INTERFACE, template<class> class TYPEINFO, typename...ARGS>
38  struct factory
39  {
40  /// Typedef for our abstract interface
41  typedef INTERFACE interface_type;
42 
43  /// Typedef for this factory type
44  typedef factory<interface_type,TYPEINFO,ARGS...> type;
45 
46  /// Template alias for typeinfo type
47  template<typename T>
48  using typeinfo_type = TYPEINFO<T>;
49 
50  /// Get key type from typeinfo struct
52 
53  /// Constructor function type
54  typedef std::function<interface_type*(ARGS...)> constructor_type;
55 
56  /// Internal type of map for storing ids
57  typedef std::unordered_map<key_type,constructor_type> class_map_type;
58 
59  /// Alias template for registar
60  template<typename T>
61  using registrar_type = registrar<T,type,ARGS...>;
62 
63  /// Checks if class with element id is registered
64  static bool exists(const key_type& _key)
65  {
66  return private_classes().count(_key) > 0;
67  }
68 
69  /// Registers class with custom key
70  template<typename T>
71  static void reg(const key_type& _key)
72  {
73  if (exists(_key)) return;
75  }
76 
77  /// Registers class by getting key from registrar's type id
78  template<typename T>
79  static void reg()
80  {
81  key_type_check<T>();
83  }
84 
85  /// Unregisters class with custom key
86  static void unreg(const key_type& _key)
87  {
88  if (!exists(_key)) return;
89  private_classes().erase(_key);
90  }
91 
92  /// Unregisters class by getting key from registrar
93  template<typename T>
94  static void unreg()
95  {
96  key_type_check<T>();
98  }
99 
100  /// Instantiates an object of the class by id and constructor arguments
101  static interface_type* create(const key_type& _key, const ARGS&..._args)
102  {
103  if (!exists(_key)) return nullptr;
104  return private_classes()[_key](_args...);
105  }
106 
107  /// Gives readonly access to registered classes
108  static class_map_type const& classes()
109  {
110  return private_classes();
111  }
112 
113  private:
114  /// Checks if key types are the same
115  template<typename T>
116  static void key_type_check()
117  {
118  // Check if T is a base class of interface
119  static_assert(std::is_base_of<interface_type,T>::value,
120  "Given type T must be a base class of the interface class");
121 
122  // Check if registrar's type id and key type are the same
123  typedef std::is_same<decltype(registrar_type<T>::type_id()),key_type> is_same_type;
124  static_assert(is_same_type::value,
125  "Type of type id to be registered and registrys type id must be equal!");
126  }
127 
129  {
130  static class_map_type _classes;
131  return _classes;
132  }
133  };
134 
135  /**@brief Registrar mixin class which holds flag of registered class, to be derived from T
136  * @tparam T type of derived class
137  * @tparam REGISTRY type of registry the registrar class uses
138  * @tparam ...ARGS Template parameter which comply to the constructor signature of the interface
139  **/
140  template<typename T, typename REGISTRY, typename...ARGS>
141  struct registrar
142  {
143  /// Typedef for registry
144  typedef REGISTRY registry_type;
145 
146  /// Gets key type from registry
147  typedef typename registry_type::key_type key_type;
148 
149  /// Gets interface type from registry
150  typedef typename registry_type::interface_type interface_type;
151 
152  /// Get type info type from registry
153  typedef typename registry_type::template typeinfo_type<T> typeinfo_type;
154 
155  /// Friend of registry so registry can access registrar's private functions
157 
158  /// This static instance is responsible for auto registration
160 
161  /// Constructor of registrar registeres the object if not already registered
163  {
164  if (!registered()) registry_type::template reg<T>(type_id());
165  }
166 
167  private:
168  /// Overload assignment operator so no copying is possible
170  {
171  return *this;
172  }
173 
174  /// The class is registered when the instance is not a null pointer
175  static bool registered()
176  {
177  return instance_ != nullptr;
178  }
179 
180  /// Create an instance of the interface and return raw pointer
181  static interface_type* create(const ARGS&..._args)
182  {
183  return new T(_args...);
184  }
185 
186  /// Return type id by calling the call operator of type info template
187  static decltype(typeinfo_type()()) type_id()
188  {
189  return typeinfo_type()();
190  }
191 
192  /// Holds the instance which cares about auto registration
193  static registrar* instance()
194  {
195  static registrar theInstance;
196  instance_ = &theInstance;
197  return instance_;
198  }
199  };
200 
201  /// Our static instance
202  template<typename T, typename R, typename...ARGS>
203  registrar<T,R,ARGS...>* registrar<T,R,ARGS...>::instance_
205 }
206 
207 
208 #endif /* BOOSTX_FACTORY_HPP_ */
static void unreg()
Unregisters class by getting key from registrar.
Definition: factory.hpp:94
static void unreg(const key_type &_key)
Unregisters class with custom key.
Definition: factory.hpp:86
static bool registered()
The class is registered when the instance is not a null pointer.
Definition: factory.hpp:175
typeinfo_type< interface_type >::typeid_type key_type
Get key type from typeinfo struct.
Definition: factory.hpp:51
registry_type::template typeinfo_type< T > typeinfo_type
Get type info type from registry.
Definition: factory.hpp:153
registrar()
Constructor of registrar registeres the object if not already registered.
Definition: factory.hpp:162
std::unordered_map< key_type, constructor_type > class_map_type
Internal type of map for storing ids.
Definition: factory.hpp:57
static registrar * instance()
Holds the instance which cares about auto registration.
Definition: factory.hpp:193
registry_type::key_type key_type
Gets key type from registry.
Definition: factory.hpp:147
static interface_type * create(const key_type &_key, const ARGS &..._args)
Instantiates an object of the class by id and constructor arguments.
Definition: factory.hpp:101
friend registry_type
Friend of registry so registry can access registrar's private functions.
Definition: factory.hpp:156
Registrar mixin class which holds flag of registered class, to be derived from T. ...
Definition: factory.hpp:30
std::function< interface_type *(ARGS...)> constructor_type
Constructor function type.
Definition: factory.hpp:54
TYPEINFO< T > typeinfo_type
Template alias for typeinfo type.
Definition: factory.hpp:48
static registrar * instance_
This static instance is responsible for auto registration.
Definition: factory.hpp:159
factory< interface_type, TYPEINFO, ARGS...> type
Typedef for this factory type.
Definition: factory.hpp:44
INTERFACE interface_type
Typedef for our abstract interface.
Definition: factory.hpp:41
static class_map_type & private_classes()
Definition: factory.hpp:128
static decltype(typeinfo_type()()) type_id()
Return type id by calling the call operator of type info template.
Definition: factory.hpp:187
static interface_type * create(const ARGS &..._args)
Create an instance of the interface and return raw pointer.
Definition: factory.hpp:181
static void key_type_check()
Checks if key types are the same.
Definition: factory.hpp:116
static class_map_type const & classes()
Gives readonly access to registered classes.
Definition: factory.hpp:108
registry_type::interface_type interface_type
Gets interface type from registry.
Definition: factory.hpp:150
static void reg()
Registers class by getting key from registrar's type id.
Definition: factory.hpp:79
registrar & operator=(const registrar &)
Overload assignment operator so no copying is possible.
Definition: factory.hpp:169
REGISTRY registry_type
Typedef for registry.
Definition: factory.hpp:144
static void reg(const key_type &_key)
Registers class with custom key.
Definition: factory.hpp:71
The central factory class.
Definition: factory.hpp:38
static bool exists(const key_type &_key)
Checks if class with element id is registered.
Definition: factory.hpp:64