Skip to content

Instantly share code, notes, and snippets.

@pyrtsa
Created June 28, 2011 16:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save pyrtsa/1051564 to your computer and use it in GitHub Desktop.
Save pyrtsa/1051564 to your computer and use it in GitHub Desktop.
Object factory using Boost.Phoenix, Boost.Function and Boost.SmartPtr libraries
#include <boost/foreach.hpp>
#include <boost/function.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/variant.hpp>
#include <iostream>
#include <map>
#include <string>
#include <vector>
struct Object1 { std::string hello() const { return "Hi, Object1"; } };
struct Object2 { std::string hello() const { return "Ay, Object2"; } };
struct Object3 { std::string hi() const { return "Oh, hi!"; } };
struct bad_type_exception : std::exception {
char const * what() const throw() { return "No such class!"; }
};
typedef boost::variant<Object1, Object2, Object3> Object;
struct HelloVisitor {
typedef std::string result_type;
template <typename T> std::string operator()(T const & t) {
return t.hello(); // <-- A templated solution will handle these guys.
}
std::string operator()(Object3 const & t) {
return t.hi(); // <-- But he's a bit different, you see... ;-)
}
};
struct Factory {
typedef std::map<std::string, boost::function<Object()> > FactoryMap;
FactoryMap f;
Factory() {
using boost::phoenix::construct;
f["Object1"] = construct<Object1>();
f["Object2"] = construct<Object2>();
f["Object3"] = construct<Object3>();
// ...
}
Object operator()(std::string const & type) const {
FactoryMap::const_iterator it = f.find(type);
if (it == f.end()) throw bad_type_exception();
return it->second();
}
};
int main() {
Factory factory;
std::vector<std::string> types;
types.push_back("Object1");
types.push_back("Object3");
types.push_back("Object2");
std::vector<Object> items;
BOOST_FOREACH(std::string const & type, types)
items.push_back(factory(type));
HelloVisitor hello;
BOOST_FOREACH(Object const & item, items)
std::cout << boost::apply_visitor(hello, item) << std::endl;
// Prints:
// Hi, Object1
// Oh, hi!
// Ay, Object2
}
@pyrtsa
Copy link
Author

pyrtsa commented Jun 29, 2011

See also "improved" version with even more Phoenix stuff, in https://gist.github.com/1054616.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment