invalid cast of an rvalue expression
Axel Freyn
axel-freyn@gmx.de
Wed May 18 19:21:00 GMT 2011
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.
>
More information about the Gcc-help
mailing list