
On 3/7/2011 7:44 PM, Joel Falcou wrote:
On 07/03/11 11:48, Christopher Jefferson wrote:
Also, I would expect these problems to become more serious in C++0x code, because users will probably write expressions like:
auto i = x + y;
Which would be fine for built-in types, and introduce bugs if x or y was an xint::integer, using proto.
auto i = x + y; does what it need to do, build an expression type. The only problem will arise if x and y has a shorter life span than i, which is usually not the case in random code.
When does it happen ? When someone do something like:
auto f( X const& x) -> decltype(x+x*declval<X>()) { auto that = x + x*X(); return that; }
In this case, problem arise as X() wont be there out of f().
... and because ...
Note however than:
auto f( X const& x) -> decltype(x+x*x) { auto that = x + x*x; return that; }
do work as intended by passing along the locally constructed AST to build a larger one at calling site.
No, it doesn't. The intermediate temporary nodes will also be stored by reference, and those immediately go out of scope. "that" is already invalid when you try to return it. It's even more invalid (ok, equally invalid) when f returns.
Now, my guess is that const ref lifespan propagation still apply in 0x, so doing somethign along:
auto f( X const& x) -> decltype(x+x*declval<X const>()) { X const local; auto that = x + x*local; return that; }
will surely works (more or less, untested code). And if not, there is the only case where some deep_copy *may* be needed.
And all in all, in these particular case, i wonder if a c++0x enabled proto wont just be able to have rvalue-ref expression nodes that let it fly properly.
Applying 0x logic to 03 based code is not very correct. I'll keep this issue in mind when we'll look at porting proto in 0x, and in 0x, proto will surely be a totally different beast inside.
It remains to be seen what, if anything, can be done to make expression templates and "auto" play nicely in C++0x. But I suspect the answer is: nothing. Joel, I'm honored by your enthusiasm for Proto, but in this case, I think it's misplaced. For a simple value type like an infinite precision integer, expression templates are just plain dangerous. I could imagine a design that uses a) the small object optimization for ints below a certain threshold, and b) a ref-counted handle/body idiom for everything else (like xpressive's regex objects), where the body could be either i) a simple big-int terminal or ii) a type-erased expression template that keeps its referenced bodies alive until an evaluation is needed, and so avoid unnecessary allocations for intermediate expressions. It must be done such that adding two big-ints yields a big-int. "auto i = x + y;" simply MUST work, always, though it need not actually do any addition. But I haven't thought it all through, so that could all be bollocks. :-) -- Eric Niebler BoostPro Computing http://www.boostpro.com