$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: Douglas Gregor (gregod_at_[hidden])
Date: 2001-06-14 07:02:30
On Thursday 14 June 2001 03:43, you wrote:
> > The problem is that a bind library tends to grow uncontrollably and
>
> since
>
> > the 'Bind' part of Lambda is scheduled right after the 'Tuple'
>
> part... you
>
> > get the idea. :-)
> >
> > Identifying a 'simple' bind subset isn't easy, since different
>
> people have
>
> > different needs.
>
> I agree with the uncontrollable growth. A code that performs the
> placeholder substitutions with function composition is already over
> 'simple'. And once that part is done, why not add binding of
> operators, and why not control structures ...
>
> We're cutting LL into smaller pieces. tuples became a separate library
> as it is really quite different concept of binding. It is just a tool
> that LL uses.
> bind wont't become another library, but rather the
> user include features like bind functions, operators, control
> structures separately, and each of these include the core machinery
> to make argument substitution and return type deduction work.
>
> Anyway, I like the idea of making LL and function work together.
> But if we take that step, why confine it to just bind invocations:
>
> If something like this would work:
>
> ostream& print(ostream& o, int i) { return o << i; }
> function<ostream&, int> outputter = bind(print, ref(cout), free1)
> // ref is to make bind store cout as reference
> outputter(1);
>
> why not:
>
> function<ostream&, int> outputter = (cout << free1)
> outputter(1);
It's all the same to Boost.Function.
> One detail that requires thinking is that LL stores some of the bound
> arguments as references.
> E.g. the function object resulting from a lambda expression
> a += free1 holds a reference to a.
> In current LL this is ok, as the function objects cannot really be
> stored for future use, but are constructed and evaluated at the same
> site.
> Now, if we store the function object into a variable,
> there's a fear for dangling references.
>
> int *a = new int();
> function<int&, int> f = (*a += free1);
> f(7); // ok
> delete a;
> f(7); // dangling reference
>
> Cheers, Jaakko
Boost.Function won't be dealing with this. However, I was going to bring up 
the issue soon because a signals & slots library is on the horizon, and the 
issue is pertinent there.
Signals & slots deals with the problem of dangling references, pointers, etc. 
by removing connections when objects die. All of the signals & slots 
libraries I've seen thus far include limited binder libraries (usually just 
something that binds the "this" argument for a pointer-to-member-function) 
and when "this" dies, the connection dies. 
We don't want to do the same for Boost. Binding and deferred calls are 
orthogonal concepts, even for signals & slots. So I need a way to 
(statically) traverse all bound objects in a function object (and all 
contained function objects, etc). Then I can find all objects that are able 
to signal end-of-lifetime so that they can destroy the connection when they 
are destroyed.
Here's a possible interface: the signals & slots library defines a visitor 
class as such:
struct BindLifetimes {
  void visit(slot_base& slot);
  void visit(slot_base* slot);
  template<typename T> visit(T); // some hook for user-defined pointer types
};
The lambda library (or binding library) defines a function that traverses all 
bound objects:
template<typename LambdaFunction, typename Visitor>
inline void traverse_bound_objects(const LambdaFunction&, Visitor);
I need this sort of thing to make signals & slots work well, and of course 
I'm willing to help out on the lambda end to get it done. 
        Doug