Opened 12 years ago

Closed 12 years ago

Last modified 10 years ago

#5473 closed Patches (wontfix)

[Foreach] non-const rvalue collections are treated as const collections

Reported by: mimomorin@… Owned by: Eric Niebler
Milestone: To Be Determined Component: foreach
Version: Boost Development Trunk Severity: Problem
Keywords: Cc:

Description

In Boost.Foreach, non-const rvalue collections are treated as const collections. So the following code does not compile:

#include <vector>
#include <boost/foreach.hpp>

int main (int argc, char* argv[])
{
    BOOST_FOREACH(int& x, std::vector<int>(3)) {}
    return 0;
}

I think treating them as non-const collections is more intuitive and, at least, is consistent with C++0x range-based for.

Attachments (1)

test_mutate_rvalue.patch (1.5 KB ) - added by mimomorin@… 12 years ago.
Add mutate_rvalue.cpp and update Jamfile (a patch for libs/foreach/test/ against trunk).

Download all attachments as: .zip

Change History (6)

comment:1 by mimomorin@…, 12 years ago

I made patches for foreach.hpp and libs/foreach/test/, but I cannot attach them since the trac system rejects them as spam...

by mimomorin@…, 12 years ago

Attachment: test_mutate_rvalue.patch added

Add mutate_rvalue.cpp and update Jamfile (a patch for libs/foreach/test/ against trunk).

comment:2 by mimomorin@…, 12 years ago

Still fail to attach a patch for foreach.hpp...

The patch (will be attached) does the following:

  1. Renaming functions
  • is_const_ --> is_nonconst_lvalue_
    • Its return value is also changed.
  • is_rvalue_ --> is_nonconst_rvalue_
    • The name of recently added is_rvalue_(T&&, ...) is not changed because it does detect the rvalueness (the ellipsis parameter is no longer needed and was removed).
  1. Introducing a new macro
  • BOOST_FOREACH_IS_CONST
    • This macro returns "true" if the collection is a const lvalue/rvalue.
  1. Hacking codes for BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION (this might be an ugly hack...)
  • simple_variant
    • To deal with non-const rvalues, non-const get member function is added. This function returns non-const pointer to the (copied) collection.
    • Non-const lvalue collections are detected at compile-time, and so the non-const get function is only invoked for rvalues collections.
  • begin/end, rbegin/rend
    • These functions are modified to accept non-const collections.
    • Constness of the collection is propagated by means of auto_any_cast. If the collection is const, auto_any_cast returns const simple_variant reference. Otherwise, it returns non-const simple_variant reference.

All the tests (+ mutate_rvalue.cpp) ran successfully with the following compilers (both in C++03 and C++0x modes): gcc-4.3.5, gcc-4.4.5, gcc-4.5.2, gcc-4.6.0, clang (TOT).

comment:3 by Eric Niebler, 12 years ago

Resolution: wontfix
Status: newclosed

Please don't spend any more time on this. Mutable iteration over an rvalue collection makes no sense. I consider the fact that BOOST_FOREACH disallows it a feature. I'm surprised C++0x range-for allows it, but I don't that that's reason enough for BOOST_FOREACH to support it.

comment:4 by mimomorin@…, 12 years ago

OK, I agreed with you that mutable iteration over rvalue ranges is non-sense.

comment:5 by bernd.loerwald@…, 10 years ago

It actually is not non-sense.

Given a class being a facade container to an actual container, one might construct the facade container on the fly:

values_type values() const { return values_type (*this); }

and use it in a manipulating way:

BOOST_FOREACH (elem_type& elem, values())

with values_type having non-const iterators, that iterate over the actual container (which is referenced in values_type).

This will fail, as values() returns an rvalue, thus only const iteration is possible. It would be perfectly valid to modify the elements iterated over with the facade.

Note: See TracTickets for help on using tickets.