Topic: Proposal: require direct binding of short-lived references to rvalues
Author: RaoulGough@yahoo.co.uk ("Raoul Gough")
Date: Thu, 14 Nov 2002 17:30:54 +0000 (UTC) Raw View
After some email exchanges with Rani Sharoni, I've come up
with the following proposal to allow reference binding to
non-copyable rvalues in some cases. Rationale and some
background appear afterwards.
---- proposal ----
Replace the section of 8.5.3/5 that begins "If the
initializer expression is an rvalue" with the following:
--- If the initializer expression is an rvalue, with T2 a
class type, and ``cv1 T1'' is reference-compatible with
``cv2 T2,'' the reference is bound as follows:
--- If the lifetime of the reference does not extend
beyond the end of the full expression containing the
initializer expression, the reference is bound to
the object represented by the rvalue (see 3.10) or
to a sub-object within that object.
--- otherwise, the reference is bound in one of the
following ways (the choice is implementation-
defined):
[... continues as before - the original wording applies
unchanged to longer-lived references]
---- rationale ----
1. The intention of the current wording is to provide the
implementation freedom to construct an rvalue of class
type at an arbitrary location and copy it zero _or more_
times before binding any reference to it.
2. The standard allows code to call a member function on an
rvalue of class type (in 5.2.5, I guess). This means that
the implementation can be forced to bind the reference
directly, with no freedom to create any temporary
copies. e.g.
class nc {
nc (nc const &); // private, nowhere defined
public:
nc ();
nc const &by_ref () const { return *this; }
};
void f () {
void g (nc const &);
g (nc()); // Ill-formed
g (nc().by_ref()); // Ok - binds directly to rvalue
}
Forcing a direct binding in this way is possible wherever
the lifetime of the reference does not extend beyond the
containing full expression, since the reference returned
by the member function remains valid for this long.
3. As demonstrated above, existing implementations must
already be capable of constructing an rvalue of class
type in the "right" place the first time. Some compilers
already silently allow the direct binding of references
to non-copyable rvalues.
4. The change will not break any portable user code. It
would break any platform-specific user code that relies
on copies being performed by the particular
implementation.
---- background ----
The proposal is based on a recent discussion in this
group. I originally wanted to leave the implementation free
to copy the rvalue if there was a callable copy constructor,
and only *have* to bind directly if none was callable.
Unfortunately, a traditional compiler can't always tell
whether a function is callable or not, e.g. if the copy
constructor is declared but not defined. Rani pointed this
out in an example, and suggested that maybe trivial copy
constructors should still be allowed (by extension, maybe
wherever the compiler can determine callability). I've gone
with this version because it's simpler, and I also figure
the "as if" rule gives the compiler some freedom with POD
types anyway.
Regards,
Raoul Gough.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]