Domanda

I have the following factory function:

std::auto_ptr<IPath> PathFactory(std::string const& branch_type, CPathModel const& path_model)
{
   using namespace boost::assign;
   using namespace boost::phoenix::placeholders;

   typedef boost::function<IPath* (CPathModel const&)> PathFactoryFunction;
   typedef boost::unordered_map<std::string, PathFactoryFunction> FactoryMap;

   static FactoryMap factory_map = map_list_of<std::string, PathFactoryFunction>
      ("plu",           &phx::new_<CPluPath>)
      ("time_of_day",   &phx::new_<CTimeOfDayPath>)
      ("probability",   &phx::new_<CProbabilityPath>)
      ;

   std::auto_ptr<IPath> new_path;

   FactoryMap::const_iterator it = factory_map.find(branch_type);
   if (it != factory_map.end())
   {
      new_path.reset(it->second(path_model));
   }

   return new_path;
}

This code doesn't compile, and please note that I'm using C++03. What I'm trying to do here is create a mapping of strings to small function objects that can allocate an object of a specific type. Each object takes a single construction parameter of the same type (CPathModel const&).

phx::new_ has several overloads, so it probably isn't the best idea to refer to it directly, but I'm hoping everyone can help me find a way to use boost::phoenix to clean up this code and make the mapping work elegantly.

It seems easier at this point to just define a small template class with an overloaded () operator that takes the parameter and just does new T(p1) inside. But this is boilerplate and seems simple enough that boost must have a nice solution somewhere...

È stato utile?

Soluzione

Phoenix is utility for lazy functors.

You need none here (there is nary an expression template in sight).

So, you can make your own factory method template:

template <typename PathType> IPath* make_path(CPathModel const& model) { 
    return new PathType(model);
}

And use it:

static FactoryMap factory_map = map_list_of<std::string, PathFactoryFunction>
  ("plu",           &make_path<CPluPath>)
  ("time_of_day",   &make_path<CTimeOfDayPath>)
  ("probability",   &make_path<CProbabilityPath>)
  ;

Job done.

Although, at this point, there is zero benefit to using the map to lookup the factory. In fact, it's only wasteful. A simple switch[1] would be far superior. More so, because it removes the type erasure (implicit virtual polymorphism) in std::function.

[1] In fact, it would need to be chained ifs, or you can switch on a Perfect Hash

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top