Boost logo

Boost :

From: Dean Michael Berris (mikhailberis_at_[hidden])
Date: 2007-09-07 02:57:07


On 9/6/07, Marco Costalba <mcostalba_at_[hidden]> wrote:
> On 9/6/07, Dean Michael Berris <mikhailberis_at_[hidden]> wrote:
> >
> > dispatcher< fusion::vector<void(int), void(int,int), void(int, double)> > d;
>
> That's another design decision is not suitable for an object factory.
>

I'm not sure I follow you here...

>
> When you instantiate the dispatcher you already know _all_ the
> signatures that the dispacther will provide.
>
> But for a factory this is not true. You can register/add new
> signatures at runtime anywhere in the program.
>

I guess this would be true for languages like Python where you have
introspection and reflection built in -- allowing you to query the
type and see what available functions/methods are there and register
those during runtime, because it's inherently dynamic (the language).

> It would be if you dispacther is able to support something like this:
>
>
> dispatcher< fusion::vector<void(int), void(int,int), void(int, double)> > d;
>
> double another_foo(char*) { ... };
>
> d += fusion::vector<double(char*)>;
>
> d[0] = &another_foo;
>
> d[0]("test"); // another_foo() is called
>

I guess the problem the dispatcher is meant to solve is way different
from what your object factory is meant to address. However, something
like this comes to mind (assuming that the functionality of multiple
signatures is already in the dispatcher):

struct my_type {
  typedef dispatcher<fusion::vector<my_type*(int), my_type*(int,
int)>, std::string > registry;
  static my_type * create_1(int i) {
    return new my_type(i);
  };
  static my_type * create_2(int i, int j) {
    return new my_type(i, j);
  };
  static void init(registry & registry_) {
    registry_["my_type"] = &my_type::create_1;
    registry_["my_type"] = &my_type::create_2;
  };

  // rest of implementation of the type, including
  // constructors, methods, etc.
}

template <class T>
struct factory {
  typename T::registry registry;

  factory_base() { T::init(registry); };

  typedef typename T::registry::functor_type return_type;
  return_type & operator[] (typename t::registry::index_type index) {
    return registry[index];
  };
}

// ...
factory<my_type> my_factory;
my_type * ptr = my_factory["my_type"](1, 1);

In this approach, the factory is type specific and the initialization
of the factory falls on the actual type to be registered in the
factory -- and is enforced at compile-time leading to less bugs that
will reach runtime.

I guess my reluctance to provide flexibility at runtime will limit the
implementation of the dispatcher, which is intended to be as type-safe
and static as much as possible -- whereas a goal of your object
factory is to be flexible at runtime, which I don't see adds much
value especially to the factory pattern because you'll need to know
the types at compile-time anyway.

I see that at this point our implementations will begin to diverge
because the goals of our libraries are considerably different.

I don't mind this one bit at all though. :) Don't let that stop you
from working on your object factory. :)

-- 
Dean Michael C. Berris
http://cplusplus-soup.blogspot.com/
mikhailberis AT gmail DOT com
+63 928 7291459

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk