This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
The attached patch disallows rvalue references from binding to lvalues. This patch (against GCC 4.3.2) is not meant to be applied now; rather, it is the implementation we are using to explore a change in rvalue references that would make rvalue references much safer, particularly in combination with concepts, and is posted here for archival purposes. Here's a quick summary of the behavior that is changing. Right now, the following code is well-formed: struct X { }; void f(X&&); void g(X x) { f(x); // okay: rvalue reference binds to lvalue } This change makes the code ill-formed, because an rvalue reference can no longer bind to an lvalue: it is truly an rvalue (only) reference. Note that this does *not* impact the behavior of the common rvalue reference idioms, e.g., given void f(const X&); // #1 void f(X&&); // #2 lvalues still go to #1 and rvalues still go to #2. However, instead of that being decided by overloading (which currently picks #1 instead of #2 for lvalues), #1 becomes the only viable function for lvalues. Most users won't even notice the change :) The change in behavior becomes important if for some unrelated reason, SFINAE kicks #1 out of the overload set. In that case, the prior behavior would let #2 bind to the lvalue (e.g., silently moving from lvalues) while the proposed change would produce an error (the rvalue reference can't bind to the lvalue). How could SFINAE kick in? It's possible to do without concepts, but the simplest example involves std::list's push_back function with concepts: requires CopyConstructible<T> void push_back(const T&); // #1 requires MoveConstructible<T> void push_back(T&&); // #2 Now, given a move-only type (say, std::unique_ptr<int>), the function #1 doesn't even exist , so with the current rvalue-references proposal we'll end up silently moving from lvalues. That danger is avoided with the proposed change, because we can't call #2 with lvalues. There will be a paper in the next mailing (after the post-San Francisco mailing) that describes this in far more detail, and of course we'll be commenting on this aspect of rvalue references for CD1. All of the GCC and libstdc++ tests pass with this change, except the new rvalue_streams test, which is failing due to the str() call at the end; remove that call and rvalue stream insertion/extraction works again. This isn't a new issue, but I wanted to call attention to it because it has some impact on the usability of rvalue streams. - Doug 2008-10-10 Douglas Gregor <doug.gregor@gmail.com> * typeck.c (build_unary_op): Look through NON_LVALUE_EXPR nodes. (build_static_cast_1): Allow static_cast'ing to an rvalue reference type. * call.c (convert_class_to_reference): Don't allow binding of lvalues to rvalue references. (reference_binding): Ditto. Also, don't force a temporary when we're binding to an lvalue (that we're pretending isn't an lvalue). 2008-10-10 Douglas Gregor <doug.gregor@gmail.com> * include/debug/unordered_map (unordered_map::swap): Use lvalue reference. (unordered_multimap::swap): Ditto. * include/debug/unordered_set (unordered_set::swap): Use lvalue reference. (unordered_multiset::swap): Ditto. * include/tr1_impl/hashtable (_Hashtable::swap): Always use lvalue reference. * include/std/tuple (_Tuple_impl): Use lvalue references when explicitly specifying the template argument to std::move. * include/std/iosfwd (operator<<): Provide a forwarding operator<< that accepts rvalue streams. (operator>>): Ditto. * include/ext/vstring.h (__versa_string::swap): Always use lvalue reference. * include/bits/stl_list.h (list::swap): Ditto. * include/bits/stl_map.h (map::swap): Ditto. * include/bits/stl_set.h (set::swap): Ditto. * include/bits/stl_multimap.h (multimap::swap): Ditto. * include/bits/stl_pair.h (pair::swap): Ditto. * include/bits/stl_vector.h (vector::swap): Ditto. * include/bits/stl_deque.h (deque::swap): Ditto. * include/bits/stl_multiset.h (multiset::swap): Ditto. * include/bits/stl_iterator.h (move_iterator::operator*): Explicitly std::move the result, to convert it to an rvalue reference. * include/bits/stl_bvector.h (vector<bool>::swap): Always use lvalue reference. * include/bits/stl_tree.h (_Rb_tree::swap): Ditto. * include/bits/stl_move.h (forward): Forward lvalues (which may end up being turned into rvalues). (move): Explicitly static_cast to an rvalue. * testsuite/27_io/rvalue_streams.cc: New; test the use of rvalue streams. Works except for the fact that we can't call str() on the result. (This is an existing issue). * testsuite/23_containers/*/requirements/dr438/assign_neg.cc: Fixup line numbers. * testsuite/23_containers/*/requirements/dr438/insert_neg.cc: Ditto. * testsuite/23_containers/*/requirements/dr438/constructor_1_neg.cc: Ditto. * testsuite/23_containers/*/requirements/dr438/constructor_2_neg.cc: Ditto.
Attachment:
gcc-4.3.2-rref-bind.patch
Description: Binary data
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |