Created
June 28, 2011 16:43
-
-
Save pyrtsa/1051564 to your computer and use it in GitHub Desktop.
Object factory using Boost.Phoenix, Boost.Function and Boost.SmartPtr libraries
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
See also "improved" version with even more Phoenix stuff, in https://gist.github.com/1054616.