Board index » cppbuilder » Re: BDS2006: Variant-var as reference parameter in a method assigned to AnsiString-var
|
Clayton Arends
CBuilder Developer |
|
Clayton Arends
CBuilder Developer |
Re: BDS2006: Variant-var as reference parameter in a method assigned to AnsiString-var2008-02-18 02:18:03 AM cppbuilder3 "Alan Bellingham" < XXXX@XXXXX.COM >wrote in message QuoteOn the other hand, when someone wanders in with an outdated version different compiler versions certainly helps my newsgroup answers to be more correct. Now, if I had just chimed in before you and Jason got going. Instead, you two seem to have started off on the wrong foot. Clayton |
| Jason Cipriani
CBuilder Developer |
2008-02-18 02:22:25 AM
Re:Re: BDS2006: Variant-var as reference parameter in a method assigned to AnsiString-var
"Alan Bellingham" < XXXX@XXXXX.COM >wrote:
QuoteI have a relatively shiny copy of VC2005, which is much nicer to Forms application). Make sure you get the newest Platform SDK, it ships with the new compiler :-P . "Alan Bellingham" < XXXX@XXXXX.COM >wrote in message Quote>To be fair, it also behaves as Alan with BCB 2007 (5.93 is after the December update). Anyways you already answered this question for yourself in a previous comment: "Alan Bellingham" < XXXX@XXXXX.COM >wrote in message QuoteI'm happy for you that the current compiler has fixed this bug Bellingham quotes. I'll have to learn more about natural language processing so I can make it analyze the quotes and give you a little slider that adjusts the weasel-factor of what you get back. "Alan Bellingham" < XXXX@XXXXX.COM >wrote: Quotethose of us who've been on the group for a while |
| Hendrik Schober
CBuilder Developer |
2008-02-18 07:02:54 AM
Re:Re: BDS2006: Variant-var as reference parameter in a method assigned to AnsiString-var
Jason Cipriani < XXXX@XXXXX.COM >wrote:
Quote[...] If your function must take a Quote[...] XXXX@XXXXX.COM is never read I'm HSchober at gmx dot de "The trouble with being a god is that you've got no one to pray to." Terry Pratchett {smallsort} |
| Asger Joergensen
CBuilder Developer |
2008-02-18 09:32:04 AM
Re:Re: BDS2006: Variant-var as reference parameter in a method assigned to AnsiString-var
Hi Hendrik
Quote"The trouble with being a god is that you've got Asger |
| Jason Cipriani
CBuilder Developer |
2008-02-18 01:43:32 PM
Re:Re: BDS2006: Variant-var as reference parameter in a method assigned to AnsiString-var
"Hendrik Schober" < XXXX@XXXXX.COM >wrote in message
QuoteJason Cipriani < XXXX@XXXXX.COM >wrote: or similar). Pass that to Method(). It's a perfectly valid object, explicitly constructed by you. Method() does it's thing, possibly modifying the temporary, and when it returns and the temporary goes out of scope, the temporary is deleted. It works for two reasons: 1) The temporary is valid during the entire call to Method(). 2) It was explicitly constructed by you; therefore the compiler doesn't have to make any guesses about what to do. Somebody correct me if I'm wrong, but I'm not even actually sure if you'd call that a "temporary". Aren't "temporaries" only objects that are implicitly created by the compiler, behind the scenes? By the way, this also works: { AnsiString s; Method((Variant)s); } Same deal. The Variant() you construct there is in scope the entire call to Method(). However, the reason that works is not why you think it is. In that case ("(Variant)s"), the *only* reason it works is because AnsiString does -not- have a casting operator to a Variant, so the compiler uses the Variant constructor instead! If AnsiString has a Variant casting operator but Variant did not have an AnsiString constructor, neither of those would compile! Remember: You can pass any l-value to a function that takes things by reference. Consider the following code: struct B; struct A { A (const B&) { } }; struct B { }; void function (A &) { } int main (int, char **) { B b; function(A(b)); function((A)b); return 0; } In both cases, the compiler uses that A(const &B) constructor for "A(b)" and "(A)b", because this is the only way it can perform that conversion. In this case, both are equivalent to "A(b)". A(b) is an l-value -- i.e. the following code is valid: B b; A(b) = something_else; It is equivalent to: A(B()).operator = (something_else); Nothing wrong with that. Now consider this: struct B; struct A { }; struct B { operator A () { } }; void function (A &) { } int main (int, char **) { B b; function(A(b)); function((A)b); return 0; } This does not compile. In this case, the only way to perform the conversions A(b) and (A)b is through B's casting operator. So both are like "(A)b". This is not an l-value -- and there is a hidden temporary being created here -- that is, the A object that is implicitly copied when B's A casting operator returns. The following code is not allowed: (A)b = something_else; Just as you can't do this: int a; (double)a = 2.0; Now, as a third weird example, this is what I had posted in an earlier post. Consider this, which is about the same as above but the casting operator returns a reference instead of a copied object: struct B; struct A { }; struct B { operator A& () { static A dummy; return dummy; } }; void function (A &) { } int main (int, char **) { B b; function(A(b)); function((A)b); return 0; } This also works. The reason that this works (where the "A" cast does not work) is that in this case, (A)b is an l-value. In fact, it eventually evaluates to "dummy". No implicit objects are created behind the scenes -- no copies are made, no implicit casts. Hopefully that made sense. "(Variant)s" is legal in that case only because Variant has an AnsiString constructor, the compiler uses it, and the anonymous Variant() you *explicitly* create is valid and OK to pass by reference. You know, the more I think about it, the more I'm pretty sure that "temporaries" are things the compiler implicitly creates, rather than things you explicitly tell it to create. Jason |
| Jason Cipriani
CBuilder Developer |
2008-02-18 01:46:32 PM
Re:Re: BDS2006: Variant-var as reference parameter in a method assigned to AnsiString-var
"Jason Cipriani" < XXXX@XXXXX.COM >wrote in message
Quote"Hendrik Schober" < XXXX@XXXXX.COM >wrote in message day, I guess -- I was surprised (although in thinking about it it seems really reasonable) that the presence of a casting operator made that not work. Does anybody know what the precedence order is for ways the compiler will try to convert one object to another? There's constructors, constructors that take references, const references, casting operators that return objects, references to objects, are const or non-const... is that compiler-defined? |
| Hendrik Schober
CBuilder Developer |
2008-02-19 05:11:31 AM
Re:Re: BDS2006: Variant-var as reference parameter in a method assigned to AnsiString-var
Asger Joergensen < XXXX@XXXXX.COM >wrote:
QuoteHi Hendrik on the subject, I suggest "Small Gods". (That one got me hooked, BTW.) QuoteKind regards XXXX@XXXXX.COM is never read I'm HSchober at gmx dot de "The trouble with being a god is that you've got no one to pray to." Terry Pratchett |
| Hendrik Schober
CBuilder Developer |
2008-02-19 05:24:43 AM
Re:Re: BDS2006: Variant-var as reference parameter in a method assigned to AnsiString-var
Jason Cipriani < XXXX@XXXXX.COM >wrote:
Quote"Hendrik Schober" < XXXX@XXXXX.COM >wrote in message Look at this code: struct X {}; struct Y { Y(const X&) {} }; void f(Y&) {} void g(const Y&) {} int main() { X x; f( x ); f( Y(x) ); f( (Y)x ); g( x ); g( Y(x) ); g( (Y)x ); return 0; } Comeau Online (www.comeaucomputing.com/tryitout/) has this to say to it: Comeau C/C++ 4.3.9 (Mar 27 2007 17:24:47) for ONLINE_EVALUATION_BETA1 Copyright 1988-2007 Comeau Computing. All rights reserved. MODE:strict errors C++ C++0x_extensions "ComeauTest.c", line 13: error: a reference of type "Y &" (not const- qualified) cannot be initialized with a value of type "X" f( x ); ^ "ComeauTest.c", line 14: error: initial value of reference to non-const must be anlvalue f( Y(x) ); ^ "ComeauTest.c", line 15: error: initial value of reference to non-const must be an lvalue f( (Y)x ); ^ 3 errors detected in the compilation of "ComeauTest.c". There's little to add to this. Quote[...] a lifetime that ends at the end of the full expression it was created in (unless it's bound to a const ref...) Quote[...] XXXX@XXXXX.COM is never read I'm HSchober at gmx dot de "The trouble with being a god is that you've got no one to pray to." Terry Pratchett |
| Jason Cipriani
CBuilder Developer |
2008-02-19 11:26:51 AM
Re:Re: BDS2006: Variant-var as reference parameter in a method assigned to AnsiString-var
"Hendrik Schober" < XXXX@XXXXX.COM >wrote in message
QuoteI think I know what it does. It might even work using it. In your example, like you, I think "f(x);" should not compile for the same reason that you aren't allowed to, say, assign a void* to a char* without an explicit cast: It's nice of the compiler to make sure that I really mean to do what I'm doing and that it's not a mistake. But in the case of Y(x) and (Y)x, I am explicitly stating what I want to happen -- and I mean it. Also, I think Comeau is the one that might be screwed up here. A bold claim, I know. But check this out. Look at your errors: Quote"ComeauTest.c", line 14: error: initial value of reference to non-const about what it thinks an l-value is, as it compiles the following code with no errors or warnings, in strict mode: struct X {}; struct Y { Y(void) {} Y(const X&) {} }; int main (int, char **) { X x; Y assignme; (Y(x)) = assignme; ((Y)x) = assignme; return 0; } This is the result that I expected -- the result you got is *not* the result I expected. An l-value is something that can appear on the left side of an equal sign. Y(x) and (Y)x are both l-values. Comeau gets even more mysterious. Remember what I said before about how (Y)x only happens to be an l-value because the Y(const X&) constructor was the only way to do the conversion? And if you had no Y(const X&) constructor but you gave X a Y cast operator, then it would not work? Well, I think that I might have been wrong about that as a general statement. I observed that behavior in the Borland compiler and I believe in GCC as well (although now I don't remember and haven't retested it). But Comeau contradicts what I said, as the following code also compiles: struct Y { Y(void) {} }; struct X { operator Y (void) { return Y(); } }; int main (int, char **) { X x; Y assignme; (Y(x)) = assignme; ((Y)x) = assignme; return 0; } In this case there is no way to construct a Y from an X, but you can cast an X to a Y. Comeau still treats both Y(x) and (Y)x as l-values here, using (I'm assuming) the casting operator for both statements (just as "double(n)" and "(double)n" are both casts). I'm not sure what to think about it all. I might be missing something, but I don't think I am -- it definitely appears that Comeau is being inconsistent about what it treats as "l-values". My *theory* about Comeau here (based on nothing except that it's a possible explanation that leads to this effect) is that since not allowing you to pass these kinds of temporaries (using the broader definition) as non-const reference parameters to functions is kind of an arbitrary rule (i.e. there is no reason to disallow it other than protecting a programmer from himself), they had to code in some compiler rule to explicitly check for this situation and disallow it. They reason they had to explicitly check for this particular situation is because Y(x) and (Y)x (with the constructor -- I can't explain why it works with just a casting operator) are, in fact, l-values. I don't know why they disallow this -- is it part of the standard or do they have their own reasons? In any case, either Comeau is wrong about something, or the error message you got from Comeau is not correct, and they mean something else besides "l-values". Jason |
| Jason Cipriani
CBuilder Developer |
2008-02-19 11:42:57 AM
Re:Re: BDS2006: Variant-var as reference parameter in a method assigned to AnsiString-var
"Jason Cipriani" < XXXX@XXXXX.COM >wrote in message
Quote(Y(x)) = assignme; just do this: Y(x) = assignme; Comeau complains that 'x' was already declared. The reason is because it thinks I mean this: Y x = assignme; In other words, that I'm declaring a variable 'x' of type Y and initially assigning it to 'assignme'. You need the parentheses to clear it up. That's something I never knew. I did not try it with other compilers. Jason |
| Jason Cipriani
CBuilder Developer |
2008-02-19 06:52:04 PM
Re:Re: BDS2006: Variant-var as reference parameter in a method assigned to AnsiString-var
If you are considering replying to my post, I wouldn't think too hard about
it just yet. Instead, follow this thread on comp.lang.c++: groups.google.com/group/comp.lang.c++/browse_thread/thread/dec8c35806b61a7d I'm trying to clear stuff up there. So far I've learned/confirmed: * That broad definition of "temporary object" is indeed the correct one. * Contrary to what I thought, just because something can appear on the left side of an = sign doesn't necessarily mean it's an l-value. I -think-. And so... * ...Comeau is correct, it's my idea of an l-value that is wrong. Borland's C++ compiler should not be accepting the code that binds a temporary to a non-const reference by using the temporary's conversion constructor (BCC rejects the implicit conversion and the conversion when only a cast is available, but does not reject the conversion using a constructor -- it should reject all 3). Jason |
| Leo Siefert
CBuilder Developer |
2008-02-19 10:26:07 PM
Re:Re: BDS2006: Variant-var as reference parameter in a method assigned to AnsiString-var
Jason Cipriani wrote:
QuoteAlso, I think Comeau is the one that might be screwed up here. A bold claim, 1 Every expression is either an lvalue or an rvalue. ... 5 The result of calling a function that does not return a reference is an rvalue. ... 6 An expression which holds a temporary object resulting from a cast to a nonreference type is an rvalue (this includes the explicit creation of an object using functional notation. So I think Comeau is correct here (as in nearly all cases). Quote(Y(x)) = assignme; - Leo |
| Leo Siefert
CBuilder Developer |
2008-02-19 10:31:02 PM
Re:Re: BDS2006: Variant-var as reference parameter in a method assigned to AnsiString-var
Jason Cipriani wrote:
Quote*Contrary to what I thought, just because something can appear on 1 There are several assignment operators, all of which group right-to-left. All require a modifiable lvalue as their left operand... - Leo |
| Leo Siefert
CBuilder Developer |
2008-02-19 10:42:20 PM
Re:Re: BDS2006: Variant-var as reference parameter in a method assigned to AnsiString-var
Leo Siefert wrote:
QuoteFrom the standard: to issue one. Possibly these lines are simply ignored since logically an assignment to a temporary would be expected to have no effect. - Leo |
| Remy Lebeau (TeamB)
CBuilder Developer |
2008-02-20 01:32:52 AM
Re:Re: BDS2006: Variant-var as reference parameter in a method assigned to AnsiString-var
"Udo Weik" < XXXX@XXXXX.COM >wrote in message
QuoteWhen I now call that Method with an AnsiString-var like actual method call. That temporary is NOT passed to the AnsiString afterwards. In otherwards, the above code is functionally equivilent to the following: AnsiString AnsiStringVar; Variant tempVar; Method(tempVar); // tempVar is NOT assigned to AnsiStringVar here!!! Gambit |
