Hi Oren, On Wed, May 18, 2011 at 09:42:03AM -0700, Foster Boondoggle wrote: > > Hi Axel - Thanks for the quick reply. > > Here's the problem: The intention is that SqMatrix is nothing more than a > Matrix with the property that rows = cols. The class declaration > class SqMatrix : public Matrix {...} > reflects this. So, for example, operator * works in exactly the same way for > SqMatrix as for Matrix, and there should be no need to duplicate the code. > Meanwhile, Matrix declares operator * by > class Matrix { ... > Matrix operator * (const Matrix &) const ; > } OK -- and you define now new member-variables in SqMatrix, I hope? > Your solution has extra potential overhead due to the guts-copying of the > Matrix into the new SqMatrix. This could be overcome by using smart_ptr or > smart_array types, but that all shouldn't be necessary. What is wanted is a > cast of a base class object (the returned Matrix) to a reference to derived > class object (to a SqMatrix). However gcc (but not msvc++) rejects it. OK, so: to my knowledge gcc (and Ian) are right, msvc is wrong :-) you are not allowed to do it. > > I saw Ian's reply, but all it said was "you can't do that". That's not very > helpful - this code has been working for over a decade, so one would hope > that the "dotting i's & crossing t's" of increased language rigor would at > least leave room for a syntactic workaround giving the same (valid) semantic > result. Yes, that would be nice. but: Standard-C++ is NOT fully compatible to pre-standard C++ :-( However, if you are sure that it works fine, you can do it :-) You can do everything in C++ .... (and even more if you leave C++ a bit :-)) The secret is: you have to tell the Compiler "dear compiler, I know what I do. I know, that this memory can be used as SqMatrix, even if you don't believe so. So just trust me -- and don't verify it" -- and then you are 100% responsible (e.g. if sizeof(SqMatrix) != sizeof(Matrix), you have a problem. Or if the Destructor of SqMatrix does NOT destroy correctly the matrix or something like that, you might introduce memory errors... The syntax is: SqMatrix operator * (const SqMatrix &sm) const { return reinterpret_cast<const SqMatrix &>( static_cast<const Matrix &>(*this) * sm ); } Here, I use "static_cast" to convert "const SqMatrix &" into "const Matrix &" -- that's a "legal" conversion derived class -> base class, so I ask the compiler to verify what I'm doing (that will fail if SqMatrix would not be derived from Matrix!) And then I use "reinterpret_cast" to convert the result into a reference to a const SqMatrix. That is a "illegal" conversion, which can't be verified by the compiler. Reinterpret_cast does NOT call any conversion functions e.g. -- and I think the result is implementation defined, so add a testcase to your program to verify whether this line works as expected! HTH, Axel > > > Axel Freyn wrote: > > > > Hi Oren, > > On Wed, May 18, 2011 at 07:36:03AM -0700, Foster Boondoggle wrote: > >> > >> Hi Adam99 - Did you ever get a reply to this? I have the exact same > >> problem > >> (indeed, with SqMatrix and Matrix, though I had though I wrote the class > >> many years ago!) I can't seem to get it to compile in any form with the > >> latest gcc. > > > > Yes, that question was answered by Ian, see e.g. > > http://old.nabble.com/Re%3A-invalid-cast-of-an-rvalue-expression-p23106343.html > > The point is: It is illegal C++ :-) > > Old compilers (like g++ 4.1.2) accepted such constructs, but the new > > gcc-versions detect it as failure > > > > In addition: what this line does, is the following: > > - take "this", a pointer to a "const SqMatrix" > > - convert it to a Pointer to a "Matrix" (already problematic: you > > remove the const-ness here...) > > Yes, that's old-style C++, but equivalent to a const_cast. > > > > - take the element and multiply it with "sm" > > - convert the pointer to a constant reference to a SqMatrix > > This used to be interpreted by the compiler as just an instruction to > > reinterpret the object as being of the derived type. > > - create a copy of this reference and return it. > > How about, just return the object but understand it as being of the > > derived type. > > > > that sounds a bit complex to me. > > > > In order to propose a solution, we would need more information (e.g. how > > are the classes defined? is SqMatrix derived from Matrix? are there any > > Conversion-Operators / Copy-Constructors defined which can be used for > > this conversions? > > The easiest solution for this code segment would be to add a new > > copy-constructor to SqMatrix: > > class SqMatrix { > > public: > > explicit SqMatrix(const Matrix &m) : ...{ > > assert(m.Rows() == m.Columns()); > > .... > > } > > }; > > which verifies that m is really square, and then creates a SqMatrix from > > m (I added "explicit" in order to block implicit type-conversions Matrix > > -> SqMatrix -- this constructor has to be called directly). > > > > With that, you could rewrite your code-segment as > > > > SqMatrix operator * (const SqMatrix &sm) const { > > return SqMatrix(*(const Matrix *)this * sm); } > > > > which would be save (the type-conversion is cleanly done) and portable. > > (however, as I don't know the full code, may be this solution poses > > other problems?) > > > > Axel (I'm not adam99 ;-)) > > > > ... > > > > > > -- > View this message in context: http://old.nabble.com/invalid-cast-of-an-rvalue-expression-tp23105605p31648660.html > Sent from the gcc - Help mailing list archive at Nabble.com. >