factory.h
Go to the documentation of this file.
1 //
2 // Copyright (c) 2018, University of Edinburgh
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 //
8 // * Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of nor the names of its contributors may be used to
14 // endorse or promote products derived from this software without specific
15 // prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 // POSSIBILITY OF SUCH DAMAGE.
28 //
29 
30 #ifndef EXOTICA_CORE_FACTORY_H_
31 #define EXOTICA_CORE_FACTORY_H_
32 
33 #include <map>
34 #include <memory>
35 #include <typeinfo>
36 
37 #include <exotica_core/object.h>
38 #include <exotica_core/tools.h>
39 
41 
47 #define EXOTICA_CORE_REGISTER(BASE, TYPE, DERIV) \
48  static exotica::Registrar<BASE> EX_UNIQ(object_registrar_, __LINE__)("exotica/" TYPE, []() -> BASE* { return new DERIV(); }, #BASE); \
49  PLUGINLIB_EXPORT_CLASS(DERIV, BASE)
50 
51 #define EXOTICA_CORE_REGISTER_CORE(BASE, TYPE, DERIV) static exotica::Registrar<BASE> EX_UNIQ(object_registrar_, __LINE__)("exotica/" TYPE, []() -> BASE* { return new DERIV(); }, #BASE);
52 
53 namespace exotica
54 {
55 template <typename BaseClass>
56 class Registrar;
57 
60 template <class BaseClass>
61 class Factory : public Object
62 {
63 public:
64  friend class Registrar<BaseClass>;
65 
68  {
69  static Factory<BaseClass> factory_;
70  return factory_;
71  };
72 
76  void RegisterType(const std::string& type, BaseClass* (*creator_function)())
77  {
78  if (type_registry_.find(type) == type_registry_.end())
79  {
80  type_registry_[type] = creator_function;
81  }
82  else // I.e. it exists, then cannot re-create it!
83  {
84  ThrowPretty("Trying to register already existing type '" << type << "'!");
85  }
86  }
87 
88  std::shared_ptr<BaseClass> CreateInstance(const std::string& type)
89  {
90  auto it = type_registry_.find(type); // Attempt to find it
91  if (it != type_registry_.end()) // If exists
92  {
93  return std::shared_ptr<BaseClass>(it->second());
94  }
95  else
96  {
97  ThrowPretty("This factory does not recognize type '" << type << "' (" + base_type_ + ")");
98  }
99  }
100 
102  std::vector<std::string> GetDeclaredClasses()
103  {
104  std::vector<std::string> DeclaredClasses;
105  for (auto it = type_registry_.begin(); it != type_registry_.end(); ++it)
106  {
107  DeclaredClasses.push_back(it->first);
108  }
109  return DeclaredClasses;
110  }
111 
112 private:
114  inline explicit Factory<BaseClass>()
115  {
116  }
117 
119  std::map<std::string, BaseClass* (*)()> type_registry_;
120  std::string base_type_;
121 };
122 
126 template <typename BaseClass>
127 class Registrar
128 {
129 public:
133  Registrar(const std::string& name, BaseClass* (*creator)(), const std::string& base_type)
134  {
135  Factory<BaseClass>::Instance().base_type_ = base_type;
136  Factory<BaseClass>::Instance().RegisterType(name, creator);
137  }
138 };
139 } // namespace exotica
140 
141 #endif // EXOTICA_CORE_FACTORY_H_
#define ThrowPretty(m)
Definition: exception.h:36
std::map< std::string, BaseClass *(*)()> type_registry_
The Map containing the register of the different types of classes.
Definition: factory.h:119
Registration Class for the object type: Also templated:
Definition: factory.h:56
std::shared_ptr< BaseClass > CreateInstance(const std::string &type)
Definition: factory.h:88
Templated Object factory for Default-constructible classes. The Factory is itself a singleton...
Definition: factory.h:61
Registrar(const std::string &name, BaseClass *(*creator)(), const std::string &base_type)
Public Constructor which is only used to register the new task type.
Definition: factory.h:133
virtual std::string type() const
Type Information wrapper: must be virtual so that it is polymorphic...
Definition: object.h:61
void RegisterType(const std::string &type, BaseClass *(*creator_function)())
Registers a new derived class type.
Definition: factory.h:76
std::vector< std::string > GetDeclaredClasses()
Lists the valid implementations which are available and registered.
Definition: factory.h:102
static Factory< BaseClass > & Instance(void)
Singleton implementation: returns a reference to a singleton instance of the instantiated class...
Definition: factory.h:67
std::string base_type_
Definition: factory.h:120


exotica_core
Author(s): Yiming Yang, Michael Camilleri
autogenerated on Sat Apr 10 2021 02:34:49