Topic: static_cast to ref-to-const


Author: jpotter@falcon.lhup.edu (John Potter)
Date: Wed, 11 Sep 2002 17:54:33 +0000 (UTC)
Raw View
On Tue, 10 Sep 2002 19:59:57 +0000 (UTC), ron@sensor.com ("Ron
Natalie") wrote:

> "John Potter" <jpotter@falcon.lhup.edu> wrote in message news:3d7a986f.53867312@news.earthlink.net...

> > Yes, if we are on the same wavelength.  What I am suggesting is that a
> > reference static_cast should only be allowed if the same pointer cast
> > is a valid static_cast.  Note that valid pointer static_cast is a
> > proper subset of valid pointer reinterpret_cast.

> This will certainly break existing code.   static_cast in addition to it's
> "undo a defined conversion" role, gets used for doing what I'll call
> weak casts.   That is (using the original C definition of cast).

>     weak_cast<T>(x)

> is equivelent to

>     T invented_temporary(x);
>     invented_temporary

> If T is a const reference, then it forces a conversion.  static_cast gets used
> for this a lot especially to resolve ambiguities.

I've never seen it.  Could you give an example (or 20)?

Also comment on:

   float x(10.);
   static_cast<int const&>(x); // gives 10
   (int const&)x; // static_cast gives 10
                  // some compilers accept and differ on these two
   (int&)x; // reinterpret_cast gives bit pattern

Changing const changes semantics is usually avoided.

Thanks for joining with a real contribution.

John

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Attila.Feher@lmf.ericsson.se (Attila Feher)
Date: Tue, 10 Sep 2002 15:42:22 +0000 (UTC)
Raw View
John Potter wrote:
>
> On Sat, 7 Sep 2002 22:45:21 +0000 (UTC), wolof@freemail.hu (White
> Wolf) wrote:
>
> > John Potter wrote:
>
> > > Maybe the rule is that static_cast<T const&>(V) is valid iff for an
> > > l-value L of the same type as V static_cast<T const*>(&L) is valid.
> > > Alternatively, no new temporaries of a different type may be created
> > > from the argument.
>
> > Isn't that exactly the rule at the reinterpret_cast for ref-to-ref casts?
>
> Yes, if we are on the same wavelength.

I certainly hope so.  Since the standard says around reinterpret_cast
the same thing, I believe that your comments should be on the right
track.

> What I am suggesting is that a
> reference static_cast should only be allowed if the same pointer cast
> is a valid static_cast.

Yep.  However AFAIR Scott's example casted a type to a reference, and
not a reference to a reference - which is the case described at the
reinterpret_cast.  So it is not exactly the same rules. :-(

> Note that valid pointer static_cast is a
> proper subset of valid pointer reinterpret_cast.

OK.

A

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ron@sensor.com ("Ron Natalie")
Date: Tue, 10 Sep 2002 19:59:57 +0000 (UTC)
Raw View
"John Potter" <jpotter@falcon.lhup.edu> wrote in message news:3d7a986f.53867312@news.earthlink.net...

> Yes, if we are on the same wavelength.  What I am suggesting is that a
> reference static_cast should only be allowed if the same pointer cast
> is a valid static_cast.  Note that valid pointer static_cast is a
> proper subset of valid pointer reinterpret_cast.
>
This will certainly break existing code.   static_cast in addition to it's
"undo a defined conversion" role, gets used for doing what I'll call
weak casts.   That is (using the original C definition of cast).

    weak_cast<T>(x)

is equivelent to

    T invented_temporary(x);
    invented_temporary

If T is a const reference, then it forces a conversion.  static_cast gets used
for this a lot especially to resolve ambiguities.



---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: samaresh@juno.com (Samaresh Singh)
Date: Tue, 10 Sep 2002 20:01:42 +0000 (UTC)
Raw View
My earlier message did not quiet reflect what I actually meant.
What I meant is in the following code:
====================================================
#include <cstdlib>
#include <iostream>

using namespace std;

class Widget
{
public:
    Widget(int x) : x_(x) {}
    int getx() { return x_;}
    Widget& operator=(const Widget& rhs);
private:
    int x_;
};

Widget& Widget::operator=(const Widget& rhs)
{
  x_=rhs.x_;
return *this;
}
int main(int argc, char *argv[])
{
  int x=10;
  const Widget& rw = x;
  Widget y(7);

  const_cast<Widget&>(static_cast<const Widget&> (x) ) = y;
  cout << y.getx() << endl;
  //cout << x.getx() << endl;  //Should'nt the ouput be '7' here?

  return 0;
}
============================================================


I  tried this code using Sun compiler -> CC: WorkShop Compilers 5.0
98/12/15 C++ 5.0 <- on SunOS 5.8  and GNU C++ compiler g++ on Red Hat
Linux 7.1 operating system .

The g++ compiler on Red Hat Linux compiled properly but the Sun
compiler did
not.
The error message produced by Sun compiler was :
    Error: Using static_cast to convert from int to const Widget& not
allowed.

But though g++ compiled the static_cast staement it gave error on the
line
  cout << x.getx() << endl;
The error statement was:
     request for member 'getx' in 'x', which is of non-aggregate
type'int'

Running the debugger gdb on the executable formed with g++, I stepped
through
each line making sure that 'x' was converted into a 'Widget' through
the
invocation of Widget::WidgetI(int) constructor with value of 10.
Subsequently,
the successful assignment process was also observed using the
debugger.

Part of 5.2.9/2 states:
"An expression e can be explicitly converted to a type T using a
static_cast of the form static_cast<T>(e) if the declaration "T t(e);"
is wellformed,for some invented temporary variable t."

Now, as per the statement above x.getx() should have put the output as
7 in my opinion. But it did not.  And I think, the reason is the
static_cast statement. In reality, it did not create a 'Widget'
instance out of 'x'. And that's why that static_cast<const Widget&>(x)
is perhaps not allowed by the standard C++.

Let me know if this makes any sense.

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Mon, 9 Sep 2002 19:01:30 +0000 (UTC)
Raw View
On Sat, 7 Sep 2002 22:45:21 +0000 (UTC), wolof@freemail.hu (White
Wolf) wrote:

> John Potter wrote:

> > Maybe the rule is that static_cast<T const&>(V) is valid iff for an
> > l-value L of the same type as V static_cast<T const*>(&L) is valid.
> > Alternatively, no new temporaries of a different type may be created
> > from the argument.

> Isn't that exactly the rule at the reinterpret_cast for ref-to-ref casts?

Yes, if we are on the same wavelength.  What I am suggesting is that a
reference static_cast should only be allowed if the same pointer cast
is a valid static_cast.  Note that valid pointer static_cast is a
proper subset of valid pointer reinterpret_cast.

John

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: vAbazarov@dAnai.com ("Victor Bazarov")
Date: Thu, 5 Sep 2002 18:41:45 +0000 (UTC)
Raw View
===================================== MODERATOR'S COMMENT:
 Everyone, please don't overquote (e.g., the sig).


===================================== END OF MODERATOR'S COMMENT
"Samaresh Singh" <samaresh@juno.com> wrote...
> smeyers@aristeia.com (Scott Meyers) wrote in message
news:<MPG.17df12ae8756e04b9896e0@news.hevanet.com>...
> > I'm moving a topic over here from clcm.  The subject over there is "Cast
> > forms and reference initializations".
> >
> > 5.2.9/2 says:
> >
> >   An expression e can be explicitly converted to a type T using a
> >   static_cast of the form static_cast<T>(e) if the declaration "T t(e);"
is
> >   well-formed, for some invented temporary variable t (8.5).
> >
> > I read this as saying that if
> >
> >   T t(e);
> >
> > is okay, then
> >
> >   static_cast<T>(e)
> >
> > is, too.
> >
> > But consider this:
> >
> >   struct Widget {
> >     Widget(int);
> >   };
> >
> >   int x = 10;
> >   const Widget& rw = x;              // Line 1
> >   static_cast<const Widget&>(x);     // Line 2
> >
> > All five of my compilers accept line 1, but 3 of the 5 reject line 2:
VC7
> > and g++ 3.1 accept it, bcc 5.5.1, MWCW 6.1, and Comeau 4.3 beta #4
reject
> > it.  Line 2 sure looks legit to me, but Comeau is based on EDG, and I
can't
> > remember the last time I was right and EDG was wrong.  Besides, the
latest
> > Microsoft compiler is on my side, and surely that counts for something
:-)
> >
> > Anyway, is there some reason why 5.2.9/2 doesn't bless Line 2?
> >
> > Thanks,
> >
> > Scott
> >
> > ---
> > [ comp.std.c++ is moderated.  To submit articles, try just posting
with ]
> > [ your news-reader.  If that fails, use
lto:std-c++@ncar.ucar.edu    ]
> > [              --- Please see the FAQ before
             ]
> > [ FAQ:
n.co.uk/csc/faq.html                       ]
>
>
> If Line 2 would have compiled then, I guess, it would be legal to write:
>
>     (static_cast<const Widget&>(x)) = 7;
>
> Correct me if I am wrong.


How would that be legal?  The Widget, to which 'x' is converted,
is constant, so it is very unlikely that the assignment operator
will be called. [ The implicit copy assignment operator has the
form 'Widget& operator=(const Widget&)', IIRC ]

Victor
--
Please remove capital A's from my address when replying by mail


---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Thu, 5 Sep 2002 19:36:50 +0000 (UTC)
Raw View
In article <ef83ed35.0209041712.600a41e4@posting.google.com>, Samaresh
Singh <samaresh@juno.com> writes
>If Line 2 would have compiled then, I guess, it would be legal to write:
>
>    (static_cast<const Widget&>(x)) = 7;
>
>Correct me if I am wrong.
You cannot assign to a reference to const object.

--
Francis Glassborow      ACCU
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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: smeyers@aristeia.com (Scott Meyers)
Date: Thu, 5 Sep 2002 19:37:37 +0000 (UTC)
Raw View
On Thu, 5 Sep 2002 17:24:31 +0000 (UTC), Samaresh Singh wrote:
> If Line 2 would have compiled then, I guess, it would be legal to write:
>
>     (static_cast<const Widget&>(x)) = 7;

Notice the "const".

Scott

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.de (James Kanze)
Date: Fri, 6 Sep 2002 19:25:45 +0000 (UTC)
Raw View
jpotter@falcon.lhup.edu (John Potter) wrote in message
news:<3d768b0a.13028031@news.earthlink.net>...

> I think there is a defect, but am unsure of a good solution.

>    static_cast<const float&>(x);      // ok
>    static_cast<const float&>(10.);    // ok
>    static_cast<const float&>(10);     // error

Just at nit, but do you really think that a static_cast of a double to
float const& is/should be legal, but that of an int to float const&
isn't/should not be, or did you mean to use the constant 10.0F in the
second line?

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Sat, 7 Sep 2002 16:34:59 +0000 (UTC)
Raw View
On Fri, 6 Sep 2002 19:25:45 +0000 (UTC), kanze@gabi-soft.de (James
Kanze) wrote:

> jpotter@falcon.lhup.edu (John Potter) wrote in message
> news:<3d768b0a.13028031@news.earthlink.net>...

> > I think there is a defect, but am unsure of a good solution.

> >    static_cast<const float&>(x);      // ok
> >    static_cast<const float&>(10.);    // ok
> >    static_cast<const float&>(10);     // error

> Just at nit, but do you really think that a static_cast of a double to
> float const& is/should be legal, but that of an int to float const&
> isn't/should not be, or did you mean to use the constant 10.0F in the
> second line?

The latter, thank you.

Maybe the rule is that static_cast<T const&>(V) is valid iff for an
l-value L of the same type as V static_cast<T const*>(&L) is valid.
Alternatively, no new temporaries of a different type may be created
from the argument.

John

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: wolof@freemail.hu (White Wolf)
Date: Sat, 7 Sep 2002 22:45:21 +0000 (UTC)
Raw View
John Potter wrote:
> On Fri, 6 Sep 2002 19:25:45 +0000 (UTC), kanze@gabi-soft.de (James
> Kanze) wrote:
>
>
>>jpotter@falcon.lhup.edu (John Potter) wrote in message
>>news:<3d768b0a.13028031@news.earthlink.net>...
>
>
>>>I think there is a defect, but am unsure of a good solution.
>>
>
>>>   static_cast<const float&>(x);      // ok
>>>   static_cast<const float&>(10.);    // ok
>>>   static_cast<const float&>(10);     // error
[SNIP]
> Maybe the rule is that static_cast<T const&>(V) is valid iff for an
> l-value L of the same type as V static_cast<T const*>(&L) is valid.
> Alternatively, no new temporaries of a different type may be created
> from the argument.

Isn't that exactly the rule at the reinterpret_cast for ref-to-ref casts?

WW a.k.a Attila

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: smeyers@aristeia.com (Scott Meyers)
Date: Wed, 4 Sep 2002 18:00:00 +0000 (UTC)
Raw View
I'm moving a topic over here from clcm.  The subject over there is "Cast
forms and reference initializations".

5.2.9/2 says:

  An expression e can be explicitly converted to a type T using a
  static_cast of the form static_cast<T>(e) if the declaration "T t(e);" is
  well-formed, for some invented temporary variable t (8.5).

I read this as saying that if

  T t(e);

is okay, then

  static_cast<T>(e)

is, too.

But consider this:

  struct Widget {
    Widget(int);
  };

  int x = 10;
  const Widget& rw = x;              // Line 1
  static_cast<const Widget&>(x);     // Line 2

All five of my compilers accept line 1, but 3 of the 5 reject line 2: VC7
and g++ 3.1 accept it, bcc 5.5.1, MWCW 6.1, and Comeau 4.3 beta #4 reject
it.  Line 2 sure looks legit to me, but Comeau is based on EDG, and I can't
remember the last time I was right and EDG was wrong.  Besides, the latest
Microsoft compiler is on my side, and surely that counts for something :-)

Anyway, is there some reason why 5.2.9/2 doesn't bless Line 2?

Thanks,

Scott

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Thu, 5 Sep 2002 00:37:17 +0000 (UTC)
Raw View
On Wed, 4 Sep 2002 18:00:00 +0000 (UTC), smeyers@aristeia.com (Scott
Meyers) wrote:

> 5.2.9/2 says:

>   An expression e can be explicitly converted to a type T using a
>   static_cast of the form static_cast<T>(e) if the declaration "T t(e);" is
>   well-formed, for some invented temporary variable t (8.5).

> I read this as saying that if

>   T t(e);

> is okay, then

>   static_cast<T>(e)

> is, too.

I can't argue with that logic.

> But consider this:

>   struct Widget {
>     Widget(int);
>   };

>   int x = 10;
>   const Widget& rw = x;              // Line 1
>   static_cast<const Widget&>(x);     // Line 2

> All five of my compilers accept line 1, but 3 of the 5 reject line 2: VC7
> and g++ 3.1 accept it, bcc 5.5.1, MWCW 6.1, and Comeau 4.3 beta #4 reject
> it.  Line 2 sure looks legit to me, but Comeau is based on EDG, and I can't
> remember the last time I was right and EDG was wrong.  Besides, the latest
> Microsoft compiler is on my side, and surely that counts for something :-)

> Anyway, is there some reason why 5.2.9/2 doesn't bless Line 2?

Let me argue that it shouldn't, not that it doesn't.  Let's simplify
the example to fundamental types where we can not only observe whether
it is accepted, but what it does.

int main () {
   float x = 10;
   const int& rci = x;                          // Line 1
   cout << rci << endl;                         // Output 10
   cout << static_cast<const int&>(x) << endl;  // Line 2 Output 10

/*
I will assume that the five compilers give like results for this
example with output as indicated.  G++ does.
*/

   cout << (const int&)x << endl;

/*
If the above static_cast is accepted, this is a static_cast and should
produce the same output.  G++ treats it as reinterpret_cast with an
output indicating the bit pattern of the float.  A bug.
*/

   int& ri = x;                           // error
   cout << static_cast<int&>(x) << endl;  // error
   cout << (int&)x << endl;               // bit pattern
   }

We now have code where adding const changes the semantics of a valid
program from reinterpret_cast to static_cast.  I doubt that this was
intended.

In general, casts perform the indicated conversion and conversions on
the argument to allow the indicated conversion are forbidden by not
being specified as allowed.

   float* p = &x;
   static_cast<const int*>(p);

This code is invalid because the standard conversion from float* to
void* is suppressed on the argument.

In general, reference casts are defined in terms of equivalent pointer
casts.

   cout << *static_cast<const int*>(&x) << endl;

This code is invalid as above.

Everything seems to indicate that the static_cast should not be
allowed, yet the wording allows it.  I suggest that an attempt to
simplify the specification of static_cast resulted in allowing more
than intended.  Binding rvalues to const& has still unknown side
effects.

I think there is a defect, but am unsure of a good solution.

   static_cast<const float&>(x);      // ok
   static_cast<const float&>(10.);    // ok
   static_cast<const float&>(10);     // error

It seems that an added restriction of no conversion on the argument
may solve the problem.  The questionable cast above used two standard
conversions and the original example used a user conversion.
Alternatively, maybe the binding a const& to converted temporary is
the problem.  Changing that seems more likely to break real code than
restricting the static_cast.

Or does EDG know something about the standard which makes these
static_casts invalid?

John

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: samaresh@juno.com (Samaresh Singh)
Date: Thu, 5 Sep 2002 17:24:31 +0000 (UTC)
Raw View
smeyers@aristeia.com (Scott Meyers) wrote in message news:<MPG.17df12ae8756e04b9896e0@news.hevanet.com>...
> I'm moving a topic over here from clcm.  The subject over there is "Cast
> forms and reference initializations".
>
> 5.2.9/2 says:
>
>   An expression e can be explicitly converted to a type T using a
>   static_cast of the form static_cast<T>(e) if the declaration "T t(e);" is
>   well-formed, for some invented temporary variable t (8.5).
>
> I read this as saying that if
>
>   T t(e);
>
> is okay, then
>
>   static_cast<T>(e)
>
> is, too.
>
> But consider this:
>
>   struct Widget {
>     Widget(int);
>   };
>
>   int x = 10;
>   const Widget& rw = x;              // Line 1
>   static_cast<const Widget&>(x);     // Line 2
>
> All five of my compilers accept line 1, but 3 of the 5 reject line 2: VC7
> and g++ 3.1 accept it, bcc 5.5.1, MWCW 6.1, and Comeau 4.3 beta #4 reject
> it.  Line 2 sure looks legit to me, but Comeau is based on EDG, and I can't
> remember the last time I was right and EDG was wrong.  Besides, the latest
> Microsoft compiler is on my side, and surely that counts for something :-)
>
> Anyway, is there some reason why 5.2.9/2 doesn't bless Line 2?
>
> Thanks,
>
> Scott
>
> ---
> [ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]


If Line 2 would have compiled then, I guess, it would be legal to write:

    (static_cast<const Widget&>(x)) = 7;

Correct me if I am wrong.

Thanks
Samaresh

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]