summaryrefslogtreecommitdiff
path: root/tmpl/callable.tmpl.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'tmpl/callable.tmpl.hpp')
-rw-r--r--tmpl/callable.tmpl.hpp94
1 files changed, 94 insertions, 0 deletions
diff --git a/tmpl/callable.tmpl.hpp b/tmpl/callable.tmpl.hpp
new file mode 100644
index 0000000..900bae4
--- /dev/null
+++ b/tmpl/callable.tmpl.hpp
@@ -0,0 +1,94 @@
+// Copyright (C) by Josh Blum. See LICENSE.txt for licensing information.
+
+#ifndef INCLUDED_GRAS_CALLABLE_HPP
+#define INCLUDED_GRAS_CALLABLE_HPP
+
+#include <gras/gras.hpp>
+#include <PMC/PMC.hpp>
+#include <boost/shared_ptr.hpp>
+#include <vector>
+#include <string>
+
+namespace gras
+{
+
+/*!
+ * The callable interface allows subclasses to export public methods,
+ * but without actually exporting traditional library symbols.
+ *
+ * Callable handles the template magic so you don't have to:
+ * - registering subclass methods is simple and easy on the user.
+ * - users call registered methods with natural code aesthetics.
+ *
+ * Register a method (in the constructor of MyClass):
+ * this->register_call("set_foo", &MyClass::set_foo);
+ *
+ * Call a method on a instance of MyClass:
+ * my_class->x("set_foo", new_foo_val);
+ *
+ * Why x for the call method?
+ * - The "x" is short, one character of screen width.
+ * - The "x" looks like "*", which is commonly used.
+ * - The overloaded () operator sucks with pointers.
+ * - The overloaded () operator has template issues.
+ */
+class GRAS_API Callable
+{
+public:
+
+ //! Default constructor
+ Callable(void);
+
+ //! Destructor (virtual for subclasses)
+ virtual ~Callable(void);
+
+ //! Get a list of names for registered calls
+ std::vector<std::string> get_registered_names(void) const;
+
+protected:
+ /*!
+ * Unregister a previously registered call.
+ * Throws if the name is not found in the registry.
+ */
+ void unregister_call(const std::string &name);
+
+ /*******************************************************************
+ * Register API - don't look here, template magic, not helpful
+ ******************************************************************/
+protected:
+ #for $NARGS in range($MAX_ARGS)
+ template <typename ClassType, typename ReturnType, $expand('typename A%d', $NARGS)>
+ void register_call(const std::string &name, ReturnType(ClassType::*fcn)($expand('const A%d &', $NARGS)));
+
+ template <typename ClassType, $expand('typename A%d', $NARGS)>
+ void register_call(const std::string &name, void(ClassType::*fcn)($expand('const A%d &', $NARGS)));
+
+ #end for
+ /*******************************************************************
+ * Call API - don't look here, template magic, not helpful
+ ******************************************************************/
+public:
+ #for $NARGS in range($MAX_ARGS)
+ template <typename ReturnType, $expand('typename A%d', $NARGS)>
+ ReturnType x(const std::string &name, $expand('const A%d &', $NARGS));
+
+ template <$expand('typename A%d', $NARGS)>
+ void x(const std::string &name, $expand('const A%d &', $NARGS));
+
+ #end for
+ /*******************************************************************
+ * Private registration hooks
+ ******************************************************************/
+protected:
+ void _register_call(const std::string &, void *);
+public:
+ virtual PMCC _handle_call(const std::string &, const PMCC &);
+private:
+ boost::shared_ptr<void> _call_registry;
+};
+
+} //namespace gras
+
+#include <gras/detail/callable.hpp>
+
+#endif /*INCLUDED_GRAS_CALLABLE_HPP*/