
On 7/6/07, Lewis Hyatt <lhyatt@princeton.edu> wrote:
Let me be more precise: using BOOST_FOREACH *with rvalue containers* requires one "extra" copy. When the container is an lvalue, no copies are made, ever. You suggested binding the rvalue to a const reference. That would work, if you knew both that the object was an rvalue *and* what the type of the object was. But you don't. Instead, you have to put the object in a variant of sorts, and store a const reference to that. That's where the extra copy comes from.
For all the details, see: http://www.artima.com/cppsource/foreach.html [...] I guess, once the auto keyword is available, then you could probably avoid the copy, although you might have to make two macros, one that allows the container to be altered, and one that doesn't, or something like that.
BTW, couldn't BOOST_FOREACH internally detect if the container has a swap member function and swap the container instead of copying it: [here I assume that auto_any constructor is the source of the extra copy, but I'm not 100% sure] template<typename T, bool IsSwappable> struct auto_any : auto_any_base { auto_any(T& t) : item(t) { } mutable T item; }; template<typename T> struct auto_any <T, true>: auto_any_base { auto_any(T t) : item() { item.swap(t); } mutable T item; }; The tricky part here is that this assumes that swap does the obvious thing and T is default constructible. The former is a sensible thing to expect from a container, I'm not convinced of the latter. OTOH, this might work for non copyable but swappable containers. AFAIK, while detecting the presence of T::swap is possible [1], detecting default constructibility isn't.
Anyway, I guess this isn't such a big issue, because if copying a container is too expensive, you probably shouldn't be returning it from functions anyway...
I think that today, with NRVO widely implemented, this is no longer a problem. gpd [1] http://tinyurl.com/2abdy5