Re: Rationale of non-const reference to temporaries
Daniel Kr?gler wrote:
On 2 Dez., 16:33, "Martin T." <0xCDCDC...@gmx.at> wrote:
Daniel Kr?gler wrote:
On 1 Dez., 20:52, eca <enrico.ecam...@gmail.com> wrote:
(...)
What I know is that temporaries can be passed as const references
and that VC allows passing them as non-const references as an
extension to the standard.
What I don't know precisely is whether there is any potential risk
of error in doing as above.
Could you help me understand the rationale of the two approaches?
The reason why standard C++ decided the rules is to provide
a safety belt for you: Usually an object addressed per mutable
lvalue reference as above is supposed to modify this thingee
and that this changed state in this thingee can be evaluated
later. Now consider the following example, which was the
showstopper for allowing rvalues (like temporaries) to be
acceptable arguments for lvalue-references:
void inc(int& arg) { arg++; }
typedef long MyInt;
int main() {
MyInt i = 0;
inc(i);
if (i == 1) {
// Life-saving logic
}
}
Should this program be well-formed? If yes, how do you
estimate the chances, that this kind of *error* - hidden
in some complex software, will be finally found and fixed?
What happens in my example is that i is converted into
a *temporary* of type int, which is the actual argument
of inc. So, the seemingly induced change i never happens,
because *only* the temporary itself is modified here!
I thought there is no implicit conversion from long -> int& :
error C2664: 'inc' : cannot convert parameter 1 from 'long' to 'int &'
And this kind of code example was the reason, why C++
decided for the current rules in this regard.
How so, if it does not compile?
It does not compile, because the temporary (of type int)
cannot be bound to the lvalue-reference, just as todays'
rules are. The OP asked for the reason *why* the rules
are as they are and I provided the showstopper example
that killed an earlier attempt to *allow* binding of rvalues
to lvalue references.
The conversion long -> int happens before the binding
attempt takes places and *is* valid (and implicit). (...)
OK, so now I'm completely confused:
###
void inc(int & x) {
++x;
}
....
long lo=0;
int & ir = lo; // 1
inc(lo); // 2
inc(2); // 3
....
1) error C2440: 'initializing' : cannot convert from 'long' to 'int&' 2)
error C2664: 'inc' : cannot convert parameter 1 from 'long' to 'int&'
3) error C2664: 'inc' : cannot convert parameter 1 from 'int' to 'int&'
###
As error (1) shows, the conversion from long to int& is not possible, so
your rationale does not really make sense to me.
As I understood you correctly, you said: "If passing temporaries as
lval.ref would be possible, then an object of type long would be
implicitly converted to a temporary int object that would be passed by
reference." However, I thought (until now) that there is never any
implicit conversion to a reference type, so that cannot be the rationale
for disallowing this parameter passing.
Obviously I'm missing something?
cheers,
Martin
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]