Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
multifact.hpp
Go to the documentation of this file.
1/*
2 MULTIFACT.hpp - flexible family-of-object factory template
3
4 Copyright (C)
5 2009, Hermann Vosseler <Ichthyostega@web.de>
6
7  **Lumiera** is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License as published by the
9  Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version. See the file COPYING for further details.
11
12*/
13
57#ifndef LIB_MULTIFACT_H
58#define LIB_MULTIFACT_H
59
60
61#include "lib/error.hpp"
62#include "lib/depend.hpp"
63#include "util.hpp"
64
65#include <functional>
66#include <utility>
67#include <memory>
68#include <map>
69
70
71
72namespace lib {
73 namespace factory {
74
75 // Helpers to wrap the factory's product
76
83 template<typename TAR>
84 struct PassAsIs
85 {
86 typedef TAR RawType;
87 typedef TAR BareType;
88 typedef TAR ResultType;
89
90 template<class FUN, typename... ARGS>
92 wrap (FUN create, ARGS&&... args) noexcept
93 {
94 return create(std::forward<ARGS>(args)...);
95 }
96 };
97
98
103 template<typename RAW>
105 {
106 using RawType = std::remove_pointer<RAW>::type;
107 using BareType = RawType *;
108 using ResultType = std::shared_ptr<RawType>;
109
110 template<class FUN, typename... ARGS>
112 wrap (FUN create, ARGS&&... args)
113 {
114 return ResultType (create(std::forward<ARGS>(args)...));
115 }
116 };
117
118
130 template<typename TAR>
131 struct Build
132 {
133 template<typename RAW>
134 struct Wrapper
135 {
136 using RawType = RAW;
137 using BareType = RAW;
138 using ResultType = TAR;
139
140 using WrapFunc = std::function<ResultType(BareType)>;
141
142 void
144 {
145 this->wrapper_ = fun;
146 }
147
148 template<class FUN, typename... ARGS>
150 wrap (FUN create, ARGS&&... args)
151 {
152 return wrapper_(std::forward<BareType> (create(std::forward<ARGS>(args)...)));
153 }
154
155 private:
157 };
158 };
159
160
161
162
163
170 template<typename SIG, typename ID>
171 struct Fab
172 {
173 typedef std::function<SIG> FactoryFunc;
174
175
177 select (ID const& id)
178 {
179 if (!contains (id))
180 throw lumiera::error::Invalid("unknown factory product requested.");
181
182 return producerTable_[id];
183 }
184
185 void
186 defineProduction (ID const& id, FactoryFunc fun)
187 {
188 producerTable_[id] = fun;
189 }
190
191
192 /* === diagnostics === */
193
194 bool empty () const { return producerTable_.empty(); }
195 bool contains (ID id) const { return util::contains (producerTable_,id); }
196
197 private:
198 std::map<ID, FactoryFunc> producerTable_;
199 };
200
201
202
207 template< typename TY
208 , template<class> class Wrapper
209 >
211 {
212 using WrapFunctor = Wrapper<TY>;
213 using BareProduct = WrapFunctor::BareType;
214 using WrappedProduct = WrapFunctor::ResultType;
215
216 typedef BareProduct SIG_Fab(void);
217
218 enum{ ARGUMENT_CNT = 0 };
219 };
224 template< typename RET
225 , typename... ARGS
226 , template<class> class Wrapper
227 >
228 struct FabConfig<RET(ARGS...), Wrapper>
229 {
230 using WrapFunctor = Wrapper<RET>;
231 using BareProduct = WrapFunctor::BareType;
232 using WrappedProduct = WrapFunctor::ResultType;
233
234 typedef BareProduct SIG_Fab(ARGS...);
235
236 enum{ ARGUMENT_CNT = sizeof...(ARGS)};
237 };
238
239
240
241
242 /* === Main type === */
243
254 template< typename SIG
255 , typename ID
256 , template<class> class Wrapper = PassAsIs
257 >
259 : public FabConfig<SIG,Wrapper>::WrapFunctor
260 {
262 using SIG_Fab = _Conf::SIG_Fab;
264
266
267
268 protected:
270
271 Creator&
272 selectProducer (ID const& id)
273 {
274 return funcTable_.select(id);
275 }
276
277
278 public:
279 using Product = _Conf::WrappedProduct;
280
290 template<typename... ARGS>
291 Product
292 operator() (ID const& id, ARGS&& ...args)
293 {
294 static_assert (sizeof...(ARGS) == _Conf::ARGUMENT_CNT,
295 "MultiFac instance invoked with the wrong number "
296 "of fabrication arguments. See template parameter SIG");
297
298 Creator& creator = selectProducer (id);
299 return this->wrap (creator, std::forward<ARGS>(args)...);
300 }
301
303 template<typename... ARGS>
304 Product
305 invokeFactory (ID const& id, ARGS&& ...args)
306 {
307 return this->operator() (id, std::forward<ARGS>(args)...);
308 }
309
310
314 template<typename FUNC>
315 void
316 defineProduction (ID id, FUNC&& fun)
317 {
319 }
320
321
327 template<class IMP>
329 : lib::Depend<IMP>
330 {
332
333 Creator
335 {
336 return std::bind (&SingleFact::operator()
337 , static_cast<SingleFact*>(this));
338 }
339
340 public:
342 {
343 factory.defineProduction(id, createSingleton_accessFunction());
344 }
345 };
346
347
348 /* === diagnostics === */
349
350 bool empty () const { return funcTable_.empty(); }
351 bool contains (ID id) const { return funcTable_.contains (id); }
352 };
353
354
355
356}} // namespace lib::factory
357#endif
Access point to singletons and other kinds of dependencies designated by type.
Definition depend.hpp:281
static Factory & factory()
Definition depend.hpp:290
Convenience shortcut for automatically setting up a production line, to fabricate a singleton instanc...
Singleton(MultiFact &factory, ID id)
Factory for creating a family of objects by ID.
FabConfig< SIG, Wrapper > _Conf
void defineProduction(ID id, FUNC &&fun)
to set up a production line, associated with a specific ID
bool contains(ID id) const
_Conf::SIG_Fab SIG_Fab
Creator & selectProducer(ID const &id)
_Conf::WrappedProduct Product
_Fab::FactoryFunc Creator
Product operator()(ID const &id, ARGS &&...args)
Core operation of the factory: Select a production line and invoke the fabrication function.
Product invokeFactory(ID const &id, ARGS &&...args)
more legible alias for the function operator
Singleton services and Dependency Injection.
Lumiera error handling (C++ interface).
Policy: use a custom functor to finish the generated product.
Implementation namespace for support and library code.
LumieraError< LERR_(INVALID)> Invalid
Definition error.hpp:211
bool contains(MAP &map, typename MAP::key_type const &key)
shortcut for containment test on a map
Definition util.hpp:230
Wrapper taking ownership, by wrapping into smart-ptr.
std::remove_pointer< RAW >::type RawType
std::shared_ptr< RawType > ResultType
ResultType wrap(FUN create, ARGS &&... args)
void defineFinalWrapper(WrapFunc &&fun)
std::function< ResultType(BareType)> WrapFunc
ResultType wrap(FUN create, ARGS &&... args)
BareProduct SIG_Fab(void)
Wrapper< TY > WrapFunctor
WrapFunctor::BareType BareProduct
WrapFunctor::ResultType WrappedProduct
Table of registered production functions for MultiFact.
bool contains(ID id) const
std::function< SIG > FactoryFunc
bool empty() const
std::map< ID, FactoryFunc > producerTable_
void defineProduction(ID const &id, FactoryFunc fun)
FactoryFunc & select(ID const &id)
Dummy "wrapper", to perform the fabrication and return the unaltered product.
Definition multifact.hpp:85
ResultType wrap(FUN create, ARGS &&... args) noexcept
Definition multifact.hpp:92
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...