
If proto supported rvalue references then a could reuse foo()'s temporary resources and maybe avoid dynamic allocation for a.
I'm not actually sure that's true in the general case. foo()'s temporary is holding a value that is used in the computation. You can't reuse the memory until you are done with the value, and in the general case, that's not until you are done evaluating the expression. Consider how it works for vectors. You want to evaluate the expression as:
tmp1 = foo(); tmp2 = vector of right size for (int i in 0 to tmp2.size()-1) tmp2[i] = x[i]*y[i]+tmp1[i]*z[i]; swap(a, tmp2);
You're not ready to throw out tmp1 until after the for loop, so you need tmp2.
OK, in this isolated case, you actually /could/ use tmp1 as your scratch space:
tmp1[i] = x[i]*y[i]+tmp1[i]*z[i];
But in the general case, you can't know that it's ok to stomp a value (tmp1) that's still in use like this. And for bigint, I'm guessing that's not the case.
For sure in the general case this may not be a viable optimization, so I would probably expect proto to ignore revalue refs in the default evaluation context. Likewise the kind of fused multiply-add that you show in the vector case isn't available to me either. Imagine that each arithmetic op is a black box atomic operation (usually an external C routine - the vector/matrix equivalent would be to shell out to BLAS for example), so the only control I have is: * the order of operation. *how the expression is decomposed into the available atomics. * how many temporaries are needed to service those atomics. Also in the real-number case, functions returning result-by-value are as common as gloomy bankers (!) so the example I gave is not all that unusual - though for sure there are better gains to be made by proto-icing the most common functions (the usual transcendentals etc). I'm also able to figure out exactly when a value is used and when it's no longer needed, so if I also knew that it was a temporary already I could reuse it. Hope this explains things better, John.