Topic: static_cast<> -- what compiler is right?


Author: "Michael Andersen Nex " <nexo@imv.au.dk>
Date: 1999/10/22
Raw View
>but I do not understand why you want to make this cast.  You are trying
>to cast an rvalue of type base to a reference of type derived const.
>This would seem to be nonsensical.  What you meant to write was:
>
>return static_cast<derived> (base::operator-());
>
>This should do exactly what you expect.

Well, as far as I know, this would require a constructor along the lines,
derived::derived(const base& b) and I would rather not have that in my
current design. (See below for the "real-world" problem I'm trying to
solve...)

The reason for the question in the first place was, that I was puzzled by
the fact that:

    derived derived::operator-()
    {
        base b(base::operator-());
        return static_cast<const derived&>(b);
    }

was allowed by all my compilers, but

    derived derived::operator-()
    {
        return static_cast<const derived&>(base::operator-());
    }

was allowed by MSVC6, CodeWarrior 4 and GCC 2.95, but wasn't allowed by
BCB4. To me, the above looked functionally equivalent, and it indeed was on
3 out of 4 compilers. Furthermore, I couldn't come up with an example where
it actually would cause trouble to be able to cast from a rvalue of a
non-built-in type to a const reference. I therefore decided to throw the
question at The Collective Wisdom(TM) on the net, i.e. you guys.

"Real-world" problem:

The problem arose while I was trying to implement two template classes,
vector<class T, size_t D> and point<class T, size_t D>, by means of a common
class, base<class T, size_t D>.
By implementing all operations in the base class I only need to do partial
template specialization optimizations once for both vector and point classes
(e.g. I only need to implement an optimized base<T,2> instead of both
vector<T,2> and point<T,2>).

Now back to the implicit requirement in your suggestion: Having to add
vector<T,D>::vector(const base<T,D>& b) would suddenly allow things like:

    vector<int,2> v(2,2);
    point<int, 2> p;
    p = v;

since point<int,2>::point(const base<int,2>&) would implicitly be used
before calling point<int,2>::operator =(const point<int,2>&). That would be
contrary to what I was trying to achieve, namely to only allow *explicit*
constructions of vectors out of points and vice versa. (Now, I think of it,
this problem would be solved if the constructor taking const class base& was
private.)

Furthermore, static_cast<derived>(base::operator-()) is the equivalent of
writing
derived(base::operator-()), and that implies the construction of two objects
and not just one. Since I was (trying!) to aware of the overhead, I was
trying to avoid the construction of temporary objects as much as possible.

Regards,
Michael Nex
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/10/21
Raw View
In article <7u51b9$2u28$1@news.cybercity.dk>, Michael Andersen Nex=F8
<nexo@imv.au.dk> writes
>
>Hi,
>
>I have a question about static_cast. Consider the following code:
>
>---
>
>class base
>{
>    int x;
>public:
>    base operator-() { base res; res.x =3D -x; return res; }
>};
>
>class derived : public base
>{
>public:
>    derived operator-()
>    {
>        return static_cast<const derived&>(base::operator-());

but I do not understand why you want to make this cast.  You are trying
to cast an rvalue of type base to a reference of type derived const.
This would seem to be nonsensical.  What you meant to write was:

return static_cast<derived> (base::operator-());

This should do exactly what you expect. =20

Francis Glassborow      Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "TiTi" <TJunkMyAss@mad.scientist.com>
Date: 1999/10/15
Raw View
VC++6 does not issue an error or warning. Tried the following, and it seems
correct. It is probable though that is not legal, and that the results are
undefined (undefined behaviour). Maybe that's why the Borland Compiler
complains (original code below)


[My Try]
class base
{
    int x;
public:
  base() : x(25) {}
  base(const base& _base)
  : x(_base.x)
  {}
    base operator-()
  { base res;
   res.x = -x;
   return res; }
  void setX(int p_x)


   x = p_x;
  }
};

class derived : public base
{
public:
  derived()
  : base()
  {}
    derived operator-()
    {
        return static_cast<const derived&>(base::operator-());
    }
};

int main(void)
{
 derived d;
 derived i = -d;
 derived& r = -d;
 derived c;
 r.setX(10);
 return 0;
}


I think that the static_cast you pulled on the return of "base::operator-()"
is risky business.


TiTi



> class base
> {
>     int x;
> public:
>     base operator-() { base res; res.x = -x; return res; }
> };
> class derived : public base
> {
> public:
>     derived operator-()
>     {
>         return static_cast<const derived&>(base::operator-());
>     }
> };
> I've successfully compiled the above code snippet on gcc 2.95 and
> CodeWarrior, but Borland CBuilder 4 gets it wrong: When I compile it
> complains about converting from an value to a const reference.
>  -- Should this be considered a bug in BCB4 or are all the other compilers
> too Sloppy?





[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Michael Andersen Nex " <nexo@imv.au.dk>
Date: 1999/10/15
Raw View
Thank you, Gene.

...but, in this instance I'm not going from an rvalue to a reference, but
from an rvalue to a const reference (and gcc 2.95 + CodeWarrior
understandably doesn't accept the former, but accepts the latter).

If what you've said also holds for casting an rvalue to a const reference,
could anyone please explain why? I.e. why doesn't the standard allow:

     derived operator-()
      {
          return static_cast<const derived&>(base::operator-());
      }

...when it allows:

    derived operator-()
    {
        base res = base::operator-();
        return static_cast<const derived&>(res);
    }

Again, thanks.

/Michael Andersen Nex

Gene Bushuyev <gbush@synopsys.com> wrote in message
news:38064CE6.482F25EF@synopsys.com...
"Michael Andersen Nex   " wrote:
[snip]
>     derived operator-()
>     {
>         return static_cast<const derived&>(base::operator-());
>     }

The section 5.2.9p5 specifies the conversion from base class type to a
reference to a derived class type, but notice that it only refers to
lvalue types. Since base::operator-() returns rvalue, such conversion is
prohibited. Therefore Borland is correct producing an error.




[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Gene Bushuyev <gbush@synopsys.com>
Date: 1999/10/15
Raw View
"Michael Andersen Nex=F8" wrote:
>=20
> Thank you, Gene.
>=20
> ...but, in this instance I'm not going from an rvalue to a reference, b=
ut
> from an rvalue to a const reference (and gcc 2.95 + CodeWarrior
> understandably doesn't accept the former, but accepts the latter).
>=20
> If what you've said also holds for casting an rvalue to a const referen=
ce,
> could anyone please explain why? I.e. why doesn't the standard allow:
[snip]

I can't say why the standard is exactly the way it is, I can only have
guesses. But the only conversion for user defined types are either
pointer conversions or "lvalue of type "cv1 B", where B is a class type,
can be cast to type "reference to cv2 D", where D is a class derived
(clause 10) from B ..."(5.2.9p5) The standard doesn't allow const or
non-const casts from rvalue.

--=20
Gene Bushuyev
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Michael Andersen Nex " <nexo@imv.au.dk>
Date: 1999/10/14
Raw View
Hi,

I have a question about static_cast. Consider the following code:

---

class base
{
    int x;
public:
    base operator-() { base res; res.x = -x; return res; }
};

class derived : public base
{
public:
    derived operator-()
    {
        return static_cast<const derived&>(base::operator-());
    }
};

---

I've successfully compiled the above code snippet on gcc 2.95 and
CodeWarrior, but Borland CBuilder 4 gets it wrong: When I compile it
complains about converting from an value to a const reference.

 -- Should this be considered a bug in BCB4 or are all the other compilers
too Sloppy?

Thanks,
Michael Andersen Nex




[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Gene Bushuyev <gbush@synopsys.com>
Date: 1999/10/15
Raw View
"Michael Andersen Nex=F8" wrote:
[snip]
>     derived operator-()
>     {
>         return static_cast<const derived&>(base::operator-());
>     }

The section 5.2.9p5 specifies the conversion from base class type to a
reference to a derived class type, but notice that it only refers to
lvalue types. Since base::operator-() returns rvalue, such conversion is
prohibited. Therefore Borland is correct producing an error.

--=20
Gene Bushuyev
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]