summaryrefslogtreecommitdiff
path: root/tmpl/factory_detail.tmpl.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'tmpl/factory_detail.tmpl.hpp')
-rw-r--r--tmpl/factory_detail.tmpl.hpp64
1 files changed, 64 insertions, 0 deletions
diff --git a/tmpl/factory_detail.tmpl.hpp b/tmpl/factory_detail.tmpl.hpp
new file mode 100644
index 0000000..87a0756
--- /dev/null
+++ b/tmpl/factory_detail.tmpl.hpp
@@ -0,0 +1,64 @@
+// Copyright (C) by Josh Blum. See LICENSE.txt for licensing information.
+
+#ifndef INCLUDED_GRAS_DETAIL_FACTORY_HPP
+#define INCLUDED_GRAS_DETAIL_FACTORY_HPP
+
+#include <PMC/Containers.hpp> //PMCList
+
+namespace gras
+{
+
+/***********************************************************************
+ * Factory entry base class
+ **********************************************************************/
+struct GRAS_API FactoryRegistryEntry
+{
+ FactoryRegistryEntry(void);
+ virtual ~FactoryRegistryEntry(void);
+ virtual Element *make(const PMCC &args) = 0;
+};
+
+#for $NARGS in range($MAX_ARGS)
+/***********************************************************************
+ * Templated registration - $NARGS args
+ **********************************************************************/
+template <typename ReturnType, $expand('typename A%d', $NARGS)>
+struct FactoryRegistryEntryImpl$(NARGS) : FactoryRegistryEntry
+{
+ typedef ReturnType(*Fcn)($expand('const A%d &', $NARGS));
+ FactoryRegistryEntryImpl$(NARGS)(Fcn fcn):_fcn(fcn){}
+ Element *make(const PMCC &args)
+ {
+ const PMCList &a = args.as<PMCList>();
+ if (a.size() < $NARGS) throw a;
+ return _fcn($expand('a[%d].safe_as<A%d>()', $NARGS));
+ }
+ Fcn _fcn;
+};
+
+template <typename ReturnType, $expand('typename A%d', $NARGS)>
+void Factory::register_make(const std::string &name, ReturnType(*fcn)($expand('const A%d &', $NARGS)))
+{
+ void *r = new FactoryRegistryEntryImpl$(NARGS)<ReturnType, $expand('A%d', $NARGS)>(fcn);
+ Factory::_register_make(name, r);
+}
+
+#end for
+/***********************************************************************
+ * Templated make implementations
+ **********************************************************************/
+#for $NARGS in range($MAX_ARGS)
+template <$expand('typename A%d', $NARGS)>
+Element *Factory::make(const std::string &name, $expand('const A%d &a%d', $NARGS))
+{
+ PMCList args($NARGS);
+ #for $i in range($NARGS):
+ args[$i] = PMC_M(a$i);
+ #end for
+ return Factory::_handle_make(name, PMC_M(args));
+}
+
+#end for
+}
+
+#endif /*INCLUDED_GRAS_DETAIL_FACTORY_HPP*/