Boost logo

Boost :

From: Dean Michael Berris (mikhailberis_at_[hidden])
Date: 2007-09-30 15:19:12


On 9/30/07, Marco Costalba <mcostalba_at_[hidden]> wrote:
> On 9/30/07, Dean Michael Berris <mikhailberis_at_[hidden]> wrote:
> > >
> > > Perhaps if the key of the map is the function signature could be
> > > possible first find a match with the supplied arguments and then call
> > > the operator(), should be safe in that case. A (big) downside is that
> > > you forget implicit conversions this way.
> > >
> >
> > This is one problem with the Fusion map approach, but something I
> > perceive as really a non-issue -- because after all, the goal of the
> > library is to provide a type-safe way of implementing a dispatcher.
> >
>
> On the other way a dispatcher as long as feeds arguments to a
> wrapped-in function is natural IMHO asking to act as transparent as
> possible between the argument values and the target function, i.e.
> should be a perfect forwarder once target function has been selected
> among the stored set.
>
> Under this view if a function
>
> void foo(std::string v);
>
> can be invoked with
>
> foo("test");
>
> so should (IMHO) accept the foo wrapper and, at the end, the
> dispatcher that stores the wrapper. Just a questionable opinion ;-)
>

I don't think we're using the same terms here: the dispatcher is the
container that contains the function wrappers. The function wrappers
on the other hand, may be implemented to have multiple overloads using
a linear inheritance technique to overload operator= and operator()
which the compiler chooses statically which overload will be included.

The other more important problem with using an encapsulated Fusion
map, is that the only way the lookup is going to happen is through a
member template function with tons of overloads to support multiple
cases -- not to mention running into the forwarding problem which has
all but been beaten to death already with such libraries as Boost.Bind
among others. The implicit conversion you talk about will not be
present in the linear inheritance approach I've mentioned earlier.

If Functor<> contained a fusion map of the signatures and the actual
wrapped function, the only way it [the Functor<>] can determine which
implementation to choose is by doing something like this:

template <...>
struct Functor {
  fusion::map<
    fusion::pair<RT1(T1, T2, ..., TN), boost::function<RT1(T1, T2, ..., TN)> >,
    fusion::pair<RT2(Tt1, Tt2, ..., TtN), boost::function<RT2(Tt1,
Tt2, ..., TtN)> >
    ...
>;

  template <T1, T2, T3, T4, ..., TN>
  ReturnType operator()(T1 const & arg1, T2 const & arg2, ..., TN
const & argn) {
    return
    fusion::invoke(
      fusion::at_key<ReturnType(T1, T2, ..., TN)>(_fusion_map),
      fusion::make_tuple(T1, T2, ..., TN)
    );
  };
};

Which is messy, and doesn't solve the implicit conversion problem
you're facing either.

So the only alternative really (or at least the one I see that doesn't
run into the forwarding problem) is the linear inheritance approach
I've been mentioning. Now getting towards implementing that approach
is another discussion and effort in itself -- one I'm still mulling
around if it's even worth pursuing, given the cases I intend to cover
with the dispatcher. If at all possible, even an enhancement to
Boost.Function might be handy which will allow it to contain function
pointers to multiple signatures -- but I'm not that ambitious (yet) to
try and hack at Boost.Function to enable multiple signature support
and compile-time dispatching based on argument type lookup.

That might be something worth looking at, but that I think is a battle
I rather not fight today -- or at least not yet. :)

I think we're agreed that the Fusion map is not the best way to
approaching a solution to this problem, so please read the explanation
above as a reasoning as to why I think this is so -- and why I think
the implicit conversion is a non-issue compared to the forwarding
problem faced by such an approach. Maybe there's a simplification of
the problem by using a Fusion tuple, and doing some template
metaprogramming to find which Boost.Function member is most suitable
given a forwarding operator() implementation, but I can't wrap my head
around that just yet.

At any rate, I'm thinking maybe this multiple signature Function
wrapper thing is way too much work for little utility -- at the same
time I think it's a challenge worth tackling FWIW.

HTH :)

-- 
Dean Michael C. Berris
Software Engineer, Friendster, Inc.
[http://cplusplus-soup.blogspot.com/]
[mikhailberis_at_[hidden]]
[+63 928 7291459]
[+1 408 4049523]

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