
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 g(x); 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 app(_,x)(g); should be a compile-time error, rather than copy "x" and pass the copy to "g". The call app(_,ref(x))(g); lets the caller see the effect on "x". If the client wants to explicitly ignore the "result" of g, he can always do X dummy(x); 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@cc.gatech.edu)