summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libadhocutil/factory.h36
-rw-r--r--libadhocutil/factory.impl.h25
-rw-r--r--libadhocutil/unittests/Jamfile.jam10
-rw-r--r--libadhocutil/unittests/testFactory.cpp65
4 files changed, 136 insertions, 0 deletions
diff --git a/libadhocutil/factory.h b/libadhocutil/factory.h
new file mode 100644
index 0000000..2493525
--- /dev/null
+++ b/libadhocutil/factory.h
@@ -0,0 +1,36 @@
+#ifndef ADHOCUTIL_FACTORY_H
+#define ADHOCUTIL_FACTORY_H
+
+#include "plugins.h"
+
+namespace AdHoc {
+ template <typename Base, typename ... Params>
+ class Factory {
+ public:
+ virtual ~Factory() = 0;
+
+ virtual Base * create(const Params & ...) const = 0;
+
+ template <typename Impl, typename _ = Factory<Base, Params...>>
+ class For : public _
+ {
+ public:
+ Base * create(const Params & ... p) const override
+ {
+ return new Impl(p...);
+ }
+ };
+
+ static const Factory * get(const std::string & name);
+ static Base * create(const std::string & name, const Params & ... p);
+ };
+}
+
+#define NAMEDFACTORY(Name, Implementation, BaseFactory) \
+ NAMEDPLUGIN(Name, BaseFactory::For<Implementation>, BaseFactory)
+
+#define FACTORY(Implementation, BaseFactory) \
+ NAMEDFACTORY(#Implementation, Implementation, BaseFactory)
+
+#endif
+
diff --git a/libadhocutil/factory.impl.h b/libadhocutil/factory.impl.h
new file mode 100644
index 0000000..4e34310
--- /dev/null
+++ b/libadhocutil/factory.impl.h
@@ -0,0 +1,25 @@
+#ifndef ADHOCUTIL_FACTORY_IMPL_H
+#define ADHOCUTIL_FACTORY_IMPL_H
+
+#include "factory.h"
+
+namespace AdHoc {
+ template <typename Base, typename ... Params>
+ Factory<Base, Params ...>::~Factory() = default;
+
+ template <typename Base, typename ... Params>
+ const Factory<Base, Params...> *
+ Factory<Base, Params...>::get(const std::string & name)
+ {
+ return PluginManager::getDefault()->get<Factory>(name)->implementation();
+ }
+
+ template <typename Base, typename ... Params>
+ Base *
+ Factory<Base, Params...>::create(const std::string & name, const Params & ... p)
+ {
+ return get(name)->create(p...);
+ }
+}
+#endif
+
diff --git a/libadhocutil/unittests/Jamfile.jam b/libadhocutil/unittests/Jamfile.jam
index 77aede4..ecee7d1 100644
--- a/libadhocutil/unittests/Jamfile.jam
+++ b/libadhocutil/unittests/Jamfile.jam
@@ -129,3 +129,13 @@ run
testPlugins
;
+run
+ testFactory.cpp
+ : : :
+ <define>BOOST_TEST_DYN_LINK
+ <library>..//adhocutil
+ <library>boost_utf
+ :
+ testFactory
+ ;
+
diff --git a/libadhocutil/unittests/testFactory.cpp b/libadhocutil/unittests/testFactory.cpp
new file mode 100644
index 0000000..9b463f1
--- /dev/null
+++ b/libadhocutil/unittests/testFactory.cpp
@@ -0,0 +1,65 @@
+#define BOOST_TEST_MODULE Factory
+#include <boost/test/unit_test.hpp>
+
+#include "factory.h"
+#include "factory.impl.h"
+#include "plugins.h"
+#include "plugins.impl.h"
+
+using namespace AdHoc;
+
+class BaseThing {
+ public:
+ BaseThing(int, const std::string &){}
+
+ virtual void execute() const = 0;
+};
+
+class ImplOfThing : public BaseThing {
+ public:
+ ImplOfThing(int i, const std::string & s) : BaseThing(i, s) {}
+ void execute() const { }
+};
+class OtherImplOfThing : public BaseThing {
+ public:
+ OtherImplOfThing(int i, const std::string & s) : BaseThing(i, s) {}
+ void execute() const { }
+};
+
+typedef AdHoc::Factory<BaseThing, int, std::string> BaseThingFactory;
+
+NAMEDFACTORY("a", ImplOfThing, BaseThingFactory);
+FACTORY(OtherImplOfThing, BaseThingFactory);
+
+BOOST_AUTO_TEST_CASE( ready )
+{
+ BOOST_REQUIRE_EQUAL(2, PluginManager::getDefault()->count());
+}
+
+BOOST_AUTO_TEST_CASE( get )
+{
+ auto all = PluginManager::getDefault()->getAll();
+ auto factory1 = PluginManager::getDefault()->get<BaseThingFactory>("a")->implementation();
+ auto factory2 = BaseThingFactory::get("a");
+ auto factory3 = BaseThingFactory::get("OtherImplOfThing");
+ BOOST_REQUIRE(factory1);
+ BOOST_REQUIRE_EQUAL(factory1, factory2);
+ BOOST_REQUIRE(factory3);
+ BOOST_REQUIRE(factory1 != factory3);
+}
+
+BOOST_AUTO_TEST_CASE( create )
+{
+ auto factory1 = BaseThingFactory::get("a");
+ auto factory2 = BaseThingFactory::get("OtherImplOfThing");
+ auto i1 = factory1->create(1, "std");
+ auto i2 = factory1->create(1, "std");
+ auto i3 = factory2->create(1, "std");
+ BOOST_REQUIRE(i1);
+ BOOST_REQUIRE(i2);
+ BOOST_REQUIRE(i3);
+ BOOST_REQUIRE(i1 != i2);
+ BOOST_REQUIRE(i1 != i3);
+ BOOST_REQUIRE(i2 != i3);
+}
+