From: Brian McNamara (lorgon_at_[hidden])
Date: 2004-02-19 22:35:12
On Fri, Feb 20, 2004 at 01:25:59AM +0200, Peter Dimov wrote:
> Brian McNamara wrote:
> > Passing a non-ref-wrapped argument to a functoid that expects that
> > argument by-reference is a compile-time error.
> > Here's what we end up with
> > int x;
> > app(_,3)(f); // fine (works now)
> > app(_,x)(f); // fine (works now)
> > app(_,3)(g); // compile-time error
> > app(_,x)(g); // compile-time error // (1)
> > app(_,ref(x))(g); // works
> > There are two main ways this works different from boost::lambda.
> > At (1) (and maybe also the line above), boost would create a copy and
> > then modify the copy. In the system I envision, this would be an
> > error.
> There are some interesting subtleties here. In Lambda (and an earlier
> version of Bind), (1) will create a _const_ copy and then fail to call g.
> The current Bind, however, behaves as you describe since it follows the TR1
> proposal more closely.
> The TR1 bind specification says that "if the function application is made
> through a cv-qualified reference to, or a copy of, the function object, the
> same cv qualifiers are applied to f and aN."
> In our case, since (the equivalent of) app(_, x) is non-const, its state,
> which includes the copy of x, can be changed. But if you pass app(_, x) by
> const reference to some algorithm, app(_, x)(g) will fail.
> > (This is the desirable behavior, IMO.)
> Maybe. I'd be interested in some rationale, though. :-)
Here's my rationale; tell me what you think:
If you have a reference parameter, it's because you want to have an
effect on an argument. Examples are "in-out" or "out" parameters, where
the parameter value is changed/assigned by the function so that the new
value can be used by the caller.
As a result, passing a copy of the argument and having the function
modify the copy (as in some cases in boost::lambda) means that the
modification gets "lost". In the example
app(_,x)(g); // copy x, pass copy to g
"g" is oblivious to the fact that it's not being called as just
Whatever side-effects "g" makes to its argument never make it back to the
caller, since "app" is passing it a copy of "x". The "lost" information
probably indicates an error in the program.
As a result, I think it's preferable that
should be a compile-time error, rather than copy "x" and pass the copy
to "g". The call
lets the caller see the effect on "x". If the client wants to
explicitly ignore the "result" of g, he can always do
app(_,ref(dummy))(g); // modifies the dummy
or some such. (My hunch is that this is very rare; you don't typically
"try to ignore" reference parameter modifications.)
What do you think?
-- -Brian McNamara (lorgon_at_[hidden])
Boost list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk