BOOST_FOREACH and iterating by reference
I tried BOOST_FOREACH on a slightly modified version of the sample in the documentation. Instead of iterating by value, I iterate by reference: extern std::vector<float> get_vector_float(); BOOST_FOREACH( float& f, get_vector_float() ) { } When compiling with VisualC++ 8.0, I receive the following error message: error C2440: 'initializing' : cannot convert from 'const float' to 'float &' Conversion loses qualifiers Is there a work-around ? - Daniel -- View this message in context: http://www.nabble.com/BOOST_FOREACH-and-iterating-by-reference-tf3806531.htm... Sent from the Boost - Users mailing list archive at Nabble.com.
Daniel Gehriger wrote:
I tried BOOST_FOREACH on a slightly modified version of the sample in the documentation. Instead of iterating by value, I iterate by reference:
extern std::vector<float> get_vector_float(); BOOST_FOREACH( float& f, get_vector_float() ) { }
When compiling with VisualC++ 8.0, I receive the following error message:
error C2440: 'initializing' : cannot convert from 'const float' to 'float &' Conversion loses qualifiers
Is there a work-around ?
This is by design. get_vector_float() returns a temporary object. You can't modify it. You can get const references to the floats: BOOST_FOREACH( float const & f, get_vector_float() ) { } or you can copy the vector into a local and iterate over that: std::vector<float> v = get_vector_float(); BOOST_FOREACH( float & f, v ) { } HTH, -- Eric Niebler Boost Consulting www.boost-consulting.com
Eric Niebler wrote:
This is by design. get_vector_float() returns a temporary object. You can't modify it. --snip--
Yes, shortly after my post I came to the same conclusion. Thank you for your reply, though! My I suggest an addition to BOOST_FOREACH ? I happen to work with custom containers whose iterators are invalidated when certain member functions are called on the contained objects. So I typically use a loop pattern as follows: ------------------- for (Coll::iterator it = col.begin(); it != col.end(); /* noop */) { Coll::value_type& o = *(it++); o.destroy(); } ------------------- I adapted the BOOST_FOREACH pattern to implement this pattern: ------------------- #define FOREACH_PRE(VAR, COL) \ BOOST_FOREACH_PREAMBLE() \ if (boost::foreach_detail_::auto_any_t _foreach_col = BOOST_FOREACH_CONTAIN(COL)) {} else \ if (boost::foreach_detail_::auto_any_t _foreach_cur = BOOST_FOREACH_BEGIN(COL)) {} else \ if (boost::foreach_detail_::auto_any_t _foreach_end = BOOST_FOREACH_END(COL)) {} else \ for (bool _foreach_continue = true; \ _foreach_continue && !BOOST_FOREACH_DONE(COL); \ /* noop */) \ if (boost::foreach_detail_::set_false(_foreach_continue)) {} else \ for (VAR = BOOST_FOREACH_DEREF(COL); !_foreach_continue; _foreach_continue = true) \ if (BOOST_FOREACH_NEXT(COL), false) {} else ------------------- Would you consider adding it to Boost ? Regards, Daniel Gehriger -- View this message in context: http://www.nabble.com/BOOST_FOREACH-and-iterating-by-reference-tf3806531.htm... Sent from the Boost - Users mailing list archive at Nabble.com.
Daniel Gehriger wrote:
I happen to work with custom containers whose iterators are invalidated when certain member functions are called on the contained objects. So I typically use a loop pattern as follows:
------------------- for (Coll::iterator it = col.begin(); it != col.end(); /* noop */) { Coll::value_type& o = *(it++); o.destroy(); } -------------------
Aren't you asking for trouble here? If the call into a member function of a contained object invalidates iterators of the container that holds it and you're in the process of iterating over that container and calling such a function, then how do you know that the new value for 'it' is still points to a valid address within the container itself? -Chris
Christopher Woods wrote:
Daniel Gehriger wrote:
------------------- for (Coll::iterator it = col.begin(); it != col.end(); /* noop */) { Coll::value_type& o = *(it++); o.destroy(); } -------------------
Aren't you asking for trouble here? If the call into a member function of a contained object invalidates iterators of the container that holds it and you're in the process of iterating over that container and calling such a function, then how do you know that the new value for 'it' is still points to a valid address within the container itself?
-Chris
I wasn't precise enough: The call to the member function only invalidates the iterators pointing to the object. All other iterators remain valid. - Daniel -- View this message in context: http://www.nabble.com/BOOST_FOREACH-and-iterating-by-reference-tf3806531.htm... Sent from the Boost - Users mailing list archive at Nabble.com.
Daniel Gehriger wrote:
My I suggest an addition to BOOST_FOREACH ?
I happen to work with custom containers whose iterators are invalidated when certain member functions are called on the contained objects. So I typically use a loop pattern as follows:
------------------- for (Coll::iterator it = col.begin(); it != col.end(); /* noop */) { Coll::value_type& o = *(it++); o.destroy(); }
Are you saying that calling o.destroy() causes "it" to be invalidated? This is bad practice. If that's not the case, then vanilla FOREACH should meet your needs. Please correct me if I've misunderstood your situation. -- Eric Niebler Boost Consulting www.boost-consulting.com
Eric Niebler wrote:
Are you saying that calling o.destroy() causes "it" to be invalidated? This is bad practice. If that's not the case, then vanilla FOREACH should meet your needs. Please correct me if I've misunderstood your situation.
Yes, exactly. I wouldn't do that usually, but the collection is in fact a database table, and I use the iterators to access the records. Each record contains a field with the index of the next record (basically a singly-linked list). Destroying the record therefore invalidates the iterator pointing to the record. Pre-incrementing, however, works fine. A solution would be to cache all indices when accessing the collection, but I can't afford the overhead for this. Maybe this case is too specialized for Boost and doesn't warrant the inclusion of a BOOST_FOREACH_PRE macro in the library. - Daniel -- View this message in context: http://www.nabble.com/BOOST_FOREACH-and-iterating-by-reference-tf3806531.htm... Sent from the Boost - Users mailing list archive at Nabble.com.
participants (3)
-
Christopher Woods
-
Daniel Gehriger
-
Eric Niebler