Has anyone ever combined the classic general factory of Andrei Alexandrescu (p. 208 Chapter 8 in “Modern C ++ Design”) with the “feature-rich” features of Boost.TypeErasure ? That is, the flexibility of having several signatures of the authors' functions, which differ in the number and type of parameters (but still have the same return type and are known at compile time).
In other words, how to combine this slightly simplified common Factory:
#include <map>
#include <utility>
#include <stdexcept>
template <class AbstractProduct, typename IdentifierType, typename ProductCreator>
class Factory
{
public:
bool Register(const IdentifierType& id, ProductCreator creator) {
return associations_.emplace(id, creator).second;
}
bool Unregister(const IdentifierType& id) {
return associations_.erase(id) == 1;
}
template <typename... Arguments>
AbstractProduct CreateObject(const IdentifierType& id, Arguments&& ... args) {
auto i = associations_.find(id);
if (i != associations_.end()) {
return (i->second)(std::forward<Arguments>(args)...);
}
throw std::runtime_error("Creator not found.");
}
private:
std::map<IdentifierType, ProductCreator> associations_;
};
with this (incomplete) style of erasing a function type:
#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/builtin.hpp>
#include <boost/type_erasure/callable.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/variant.hpp>
template<class... Sig>
using multifunction = any< mpl::vector< copy_constructible<>, typeid_<>, relaxed, callable<Sig>... > >;
using variant_type = boost::make_recursive_variant< void, double, ... >::type;
using function_type = multifunction<AbstractProduct(void), AbstractProduct(double), AbstractProduct(double, double)>;
class variant_handler
{
public:
void handle(const variant_type& arg) {
boost::apply_visitor(impl, arg);
}
void set_handler(function_type f) {
impl.f = f;
}
private:
struct dispatcher : boost::static_visitor<void>
{
template<class T>
void operator()(const T& t) { f(t); }
void operator()(const vector_type& v)
{
boost::for_each(v, boost::apply_visitor(*this));
}
function_type f;
};
dispatcher impl;
};
So in the end it can be used like this:
Factory<Arity*, int, ???> factory;
factory.Register(0, boost::bind( boost::factory<Nullary *>() ));
factory.Register(1, boost::bind( boost::factory<Unary *>(), _1 ));
auto x = factory.CreateObject(0);
auto y = factory.CreateObject(1, 0.5);
, . , boost::bind() function_type, SO. , ProductCreator Register - .
, , , factory, , . , , .
++ 11, , , ++ 14 , none ..
!