SMTK  @SMTK_VERSION@
Simulation Modeling Tool Kit
Generator.h
Go to the documentation of this file.
1 //=========================================================================
2 // Copyright (c) Kitware, Inc.
3 // All rights reserved.
4 // See LICENSE.txt for details.
5 //
6 // This software is distributed WITHOUT ANY WARRANTY; without even
7 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8 // PURPOSE. See the above copyright notice for more information.
9 //=========================================================================
10 
11 #ifndef smtk_common_Generator_h
12 #define smtk_common_Generator_h
13 
14 #include "smtk/common/CompilerInformation.h"
15 
16 #include <algorithm>
17 #include <cassert>
18 #include <memory>
19 #include <set>
20 
21 #define DEBUG_GENERATOR 0
22 
23 #if !defined(NDEBUG) && DEBUG_GENERATOR
24 #include <iostream>
25 #endif
26 
27 namespace smtk
28 {
29 namespace common
30 {
31 
93 
94 namespace detail
95 {
97 {
98 };
99 } // namespace detail
100 
105 template<class Input, class Output, class Base = detail::NullGeneratorBase>
106 class GeneratorBase : public Base
107 {
108 public:
109  template<typename... T>
110  GeneratorBase(T&&... all)
111  : Base(std::forward<T>(all)...)
112  {
113  }
114 
115  virtual ~GeneratorBase() = default;
116 
122  virtual bool valid(const Input&) const = 0;
123 
128  virtual Output operator()(const Input&) = 0;
129 };
130 
136 template<class Input, class Output, class Base = detail::NullGeneratorBase>
137 class Generator : public GeneratorBase<Input, Output, Base>
138 {
139  template<class U, class V, class W, class X>
140  friend class GeneratorType;
141 
142 public:
143  template<typename... T>
144  Generator(T&&... all)
145  : GeneratorBase<Input, Output, Base>(std::forward<T>(all)...)
146  {
147  }
148 
151  bool valid(const Input&) const override;
152 
157  Output operator()(const Input&) override;
158 
159 protected:
164  static std::weak_ptr<std::set<GeneratorBase<Input, Output, Base>*>> generators();
165 };
166 
167 template<class Input, class Output, class Base>
168 std::weak_ptr<std::set<GeneratorBase<Input, Output, Base>*>>
170 {
171  static std::shared_ptr<std::set<GeneratorBase<Input, Output, Base>*>> generators =
172  std::make_shared<std::set<GeneratorBase<Input, Output, Base>*>>(
173  std::set<GeneratorBase<Input, Output, Base>*>());
174  return generators;
175 }
176 
177 template<class Input, class Output, class Base>
178 bool Generator<Input, Output, Base>::valid(const Input& input) const
179 {
180  auto gens = Generator<Input, Output, Base>::generators().lock();
181  if (gens == nullptr)
182  {
183  return false;
184  }
185  return std::any_of(
186  gens->begin(), gens->end(), [&input](const GeneratorBase<Input, Output, Base>* gen) {
187  return gen->valid(input);
188  });
189 }
190 
191 template<class Input, class Output, class Base>
193 {
194  Output output;
195  auto gens = Generator<Input, Output, Base>::generators().lock();
196  if (gens == nullptr)
197  {
198  return output;
199  }
200  for (auto gen : *gens)
201  {
202  if (!gen->valid(input))
203  {
204  continue;
205  }
206 
207  try
208  {
209  output = (*gen)(input);
210  break;
211  }
212  catch (std::exception& e)
213  {
214 #if !defined(NDEBUG) && DEBUG_GENERATOR
215  std::cerr << "Exception caught: " << e.what() << std::endl;
216 #else
217  (void)e;
218 #endif
219  }
220  }
221  return output;
222 }
223 
227 template<class Input, class Output, class Self, class Base = detail::NullGeneratorBase>
228 class GeneratorType : public GeneratorBase<Input, Output, Base>
229 {
234  class Registry
235  {
236  friend GeneratorType;
237 
238  Registry(std::weak_ptr<std::set<GeneratorBase<Input, Output, Base>*>> generators)
239  : m_generators(generators)
240  , m_self(new Self())
241  {
242  if (auto gens = m_generators.lock())
243  {
244  gens->insert(m_self);
245  }
246  }
247  ~Registry()
248  {
249  if (auto gens = m_generators.lock())
250  {
251  gens->erase(m_self);
252  }
253  delete m_self;
254  }
255  std::weak_ptr<std::set<GeneratorBase<Input, Output, Base>*>> m_generators;
256  Self* m_self;
257  };
258 
259  friend Self;
260 
261 public:
262  static bool registerClass();
263 
264 protected:
265  template<typename... T>
266  GeneratorType(T&&... all)
267  : GeneratorBase<Input, Output, Base>(std::forward<T>(all)...)
268  {
269  }
270 
271 private:
272  static bool s_registered;
273 };
274 
275 template<class Input, class Output, class Self, class Base>
277 {
278  static bool registered = false;
279  if (!registered)
280  {
281  static Registry registry(Generator<Input, Output, Base>::generators());
282  registered = true;
283  }
284  return registered;
285 }
286 
287 template<class Input, class Output, class Self, class Base>
288 bool GeneratorType<Input, Output, Self, Base>::s_registered =
289  GeneratorType<Input, Output, Self, Base>::registerClass();
290 } // namespace common
291 } // namespace smtk
292 
293 #endif
smtk
The main namespace for the Simulation Modeling Tool Kit (SMTK).
Definition: doc.h:33
smtk::common::Generator::valid
bool valid(const Input &) const override
Loop over registered generators and return true if any of the generators' valid() calls return true; ...
Definition: Generator.h:178
smtk::common::detail::NullGeneratorBase
Definition: Generator.h:96
smtk::common::Generator::generators
static std::weak_ptr< std::set< GeneratorBase< Input, Output, Base > * > > generators()
Even though the set of generators is static, we cannot guarantee its existence across compilation uni...
Definition: Generator.h:169
smtk::common::Generator
Interface generator class.
Definition: Generator.h:137
smtk::common::GeneratorType
Base class for specific generator types.
Definition: Generator.h:228
smtk::common::GeneratorBase
Base for all generators.
Definition: Generator.h:106
smtk::common::GeneratorBase::operator()
virtual Output operator()(const Input &)=0
Function call operator for generating Output-s.
smtk::common::GeneratorBase::valid
virtual bool valid(const Input &) const =0
A discriminating method to determine whether or not the input should be considered for use as input b...
smtk::common::Generator::operator()
Output operator()(const Input &) override
Loop over registered generators and return an Output instance from the first generator (a) whose vali...
Definition: Generator.h:192