Replacing old C-style casts with static|reinterpret_cast?

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Replacing old C-style casts with static|reinterpret_cast?

Daniel Boles
Murray mentioned on a Bugzilla that replacing these with static_cast<> is always good.

Is the same true for cases where we need reinterpret_cast<> ? That is semi frequent because GTK+ types are opaque even to us, so converting pointers cannot use static_cast<> as the latter cannot verify that e.g. both types have the same 1st member.

The raw C cast would ultimately boil down to a reinterpret_cast anyway, so my POV is that we should explicitly write the latter, as it signals that we know what we're doing - rather than the raw cast, which only really says 'try everything you can think of, and pick anything that barely works'!

Cheers,
Daniel


_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Fwd: Replacing old C-style casts with static|reinterpret_cast?

Daniel Boles
On 10 May 2017 at 17:45, Nicklas Karlsson <[hidden email]> wrote:
> Murray mentioned on a Bugzilla that replacing these with static_cast<> is
> always good.

I think static_cast<> is very clear with what happens, data should not be changed just intepreted as the wanted type. There are cases then exactly this is needed and then it is really good.


There's no debate about static_cast, only reinterpret_cast.

That said, it's not true that static_cast only causes reinterpretation as the desired type: it can also invoke a conversion operator, which can then return absolutely anything.

static_cast only ensures that the compiler can find a previously defined route to perform the conversion, be it a relation by basic type class or inheritance, a conversion operator, or probably various other things I can't think of right now.

In fact, due to it being satisfied by an inheritance relationship, you can e.g. cast a Gtk::Widget* that really points at a Gtk::Label to a Gtk::Frame, and it won't complain, because it assumes you typed a sensible thing: it only checks the definedness of the conversion, not the potential danger level.



_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Replacing old C-style casts with static|reinterpret_cast?

Chris Vine-3
In reply to this post by Daniel Boles
On Wed, 10 May 2017 17:22:51 +0100
Daniel Boles <[hidden email]> wrote:

> Murray mentioned on a Bugzilla that replacing these with
> static_cast<> is always good.
>
> Is the same true for cases where we need reinterpret_cast<> ? That is
> semi frequent because GTK+ types are opaque even to us, so converting
> pointers cannot use static_cast<> as the latter cannot verify that
> e.g. both types have the same 1st member.
>
> The raw C cast would ultimately boil down to a reinterpret_cast
> anyway, so my POV is that we should explicitly write the latter, as
> it signals that we know what we're doing - rather than the raw cast,
> which only really says 'try everything you can think of, and pick
> anything that barely works'!

You can use reinterpret_cast when casting between C types which employ
"C style" inheritance (that is, where the "parent" is a struct which is
the first member of the "child" struct).  This is because C structs are
of necessity standard layout types in C++ speak.  More to the point,
because such inheritance is not inheritance in the C++ sense (they are
unrelated types from the C++ inheritance point of view) casting can
only be done using a C cast or a reinterpret_cast, which is guaranteed
to work by §9.2/20 of the C++ standard.

If that was what your post was about, then I think you are fine.  But
if you were looking at casting more broadly, you cannot assume that any
other valid C cast can be replaced by a reinterpret_cast.  This is
because C casts degrade according to the order set out in §5.4/4 of the
C++ standard, and they will only be implemented as a reinterpret_cast
where a static_cast is not available (and of course a reinterpret_cast
cannot perform a const cast).

This is important because a static cast (and so a C cast) can
be used to navigate an inheritance graph of types which do not have
standard layout, and will adjust pointer addresses on casting
automatically.  This means that, amongst other things, a static_cast can
cast between, say, a virtual derived class and its non-virtual base
(objects of which will generally have different addresses because of
the vtable of the derived class), and also between derived types and
base types where multiple inheritance is employed.  reinterpret_cast on
the other hand will never adjust pointer addresses and will give
undefined behaviour in such cases.

As it happens, one cast can only be made using a C style cast.  A C
style cast will allow you to cast from a derived type to its private
base (that is, where private inheritance is used), even if both are not
standard layout types, and make the correct pointer adjustment.
static_cast will refuse the cast, and reinterpret_cast will allow it
but give undefined behaviour where pointer adjustments would be
required for the cast to succeed.

Except when navigating "C style" or "C++ style" inheritance graphs,
reinterpret_cast and C casts both give rise to strict aliasing issues
when using them for type punning (§3.10/10 of the standard), but that
is a separate matter.

You probably know all this but that wasn't clear from your question.

Chris
_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Replacing old C-style casts with static|reinterpret_cast?

Daniel Boles


On 10 May 2017 at 20:15, Chris Vine <[hidden email]> wrote:

You can use reinterpret_cast when casting between C types which employ
"C style" inheritance (that is, where the "parent" is a struct which is
the first member of the "child" struct).  This is because C structs are
of necessity standard layout types in C++ speak.  More to the point,
because such inheritance is not inheritance in the C++ sense (they are
unrelated types from the C++ inheritance point of view) casting can
only be done using a C cast or a reinterpret_cast, which is guaranteed
to work by §9.2/20 of the C++ standard.

If that was what your post was about, then I think you are fine.

Thanks for the thoughts!

Yeah, the cases I am pondering at the moment are casts between GObjects, using the typical mode of inheritance that you described. static_cast<> doesn't work, but reinterpret_cast<> seems to. It sounds like this is a case for which reinterpret_cast<> does work, and not one of the perilous ones that you mentioned later.

Do you have any recommended reading on the cases which C casts can handle, and adjust as required, but reinterpret_cast<> cannot? That was surprising to me as I thought the C++ casts could cover all the angles.


_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Replacing old C-style casts with static|reinterpret_cast?

Daniel Boles
On 10 May 2017 at 20:24, Daniel Boles <[hidden email]> wrote:

Do you have any recommended reading on the cases which C casts can handle, and adjust as required, but reinterpret_cast<> cannot? That was surprising to me as I thought the C++ casts could cover all the angles.

Sorry, of course I meant 'reinterpret_cast<> and any other C++ casts', i.e. cases that only the old C cast can handle. Some examples of discussion and a note of the relevant Standard bits (I have the PDF open permanently but never have much luck searching!) would be much appreciated.

_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Replacing old C-style casts with static|reinterpret_cast?

Chris Vine-3
On Wed, 10 May 2017 20:25:49 +0100
Daniel Boles <[hidden email]> wrote:

> On 10 May 2017 at 20:24, Daniel Boles <[hidden email]> wrote:
>
> >
> > Do you have any recommended reading on the cases which C casts can
> > handle, and adjust as required, but reinterpret_cast<> cannot? That
> > was surprising to me as I thought the C++ casts could cover all the
> > angles.
>
> Sorry, of course I meant 'reinterpret_cast<> and any other C++
> casts', i.e. cases that only the old C cast can handle. Some examples
> of discussion and a note of the relevant Standard bits (I have the
> PDF open permanently but never have much luck searching!) would be
> much appreciated.

I don't have any recommended reading I am afraid.  The ability to use C
casts to cast from derived to private base is required by these words
in §5.4/4 of C++14, in describing the behaviour of C casts:  "The same
semantic restrictions and behaviors apply, with the exception that in
performing a static_cast in the following situations the conversion is
valid even if the base class is inaccessible" .

Therefore, C casts can cast as if by static_cast to inaccessible types
even where static_cast cannot.

Chris
_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Fwd: Replacing old C-style casts with static|reinterpret_cast?

Daniel Boles

On 10 May 2017 at 20:51, Chris Vine <[hidden email]> wrote:

I don't have any recommended reading I am afraid.  The ability to use C
casts to cast from derived to private base is required by these words
in §5.4/4 of C++14, in describing the behaviour of C casts:  "The same
semantic restrictions and behaviors apply, with the exception that in
performing a static_cast in the following situations the conversion is
valid even if the base class is inaccessible" .

Therefore, C casts can cast as if by static_cast to inaccessible types
even where static_cast cannot.


No worries, a Standard reference is a good enough jumping-off point! I'll be sure to start reading that just when I want to go to sleep. :) Definitely sounds like another corner of the C/C++ maze that I didn't know about yet. Thanks.
 


_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Replacing old C-style casts with static|reinterpret_cast?

Daniel Boles
In reply to this post by Daniel Boles
Murray and Kjell: Any thoughts on the prospect of replacing C style casts with reinterpret_cast where appropriate? Chiefly, when converting between opaque (and thus not static_castable, and also probably breaking aliasing rules...) pointers to GObjects at different levels of the inheritance hierarchy.

I did prepare a patch doing this for master, which I think covered all or most instances, and compiled - and can't foresee any possible issues - but obviously discussion is needed (and my foresight is not exactly renowned).

If this works, then it would be another nice C++ification to see throughout the codebase.

Cheers!
Daniel


_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Replacing old C-style casts with static|reinterpret_cast?

Kjell Ahlstedt-2
Den 2017-05-19 kl. 17:04, skrev Daniel Boles:

> Murray and Kjell: Any thoughts on the prospect of replacing C style
> casts with reinterpret_cast where appropriate? Chiefly, when
> converting between opaque (and thus not static_castable, and also
> probably breaking aliasing rules...) pointers to GObjects at different
> levels of the inheritance hierarchy.
>
> I did prepare a patch doing this for master, which I think covered all
> or most instances, and compiled - and can't foresee any possible
> issues - but obviously discussion is needed (and my foresight is not
> exactly renowned).
>
> If this works, then it would be another nice C++ification to see
> throughout the codebase.
>
> Cheers!
> Daniel
>
reinterpret_cast is already used for conversion between different levels
of the GObject inheritance hierarchy, e.g. in the gobj() methods
generated by _CLASS_GOBJECT, _CLASS_INTERFACE and _CLASS_GTKOBJECT. But
it's not used consistently in other situations. I see no harm in using
it consistently.

Kjell
_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Replacing old C-style casts with static|reinterpret_cast?

Kjell Ahlstedt-2
Den 2017-05-20 kl. 11:51, skrev Kjell Ahlstedt:

> Den 2017-05-19 kl. 17:04, skrev Daniel Boles:
>> Murray and Kjell: Any thoughts on the prospect of replacing C style
>> casts with reinterpret_cast where appropriate? Chiefly, when
>> converting between opaque (and thus not static_castable, and also
>> probably breaking aliasing rules...) pointers to GObjects at
>> different levels of the inheritance hierarchy.
>>
>> I did prepare a patch doing this for master, which I think covered
>> all or most instances, and compiled - and can't foresee any possible
>> issues - but obviously discussion is needed (and my foresight is not
>> exactly renowned).
>>
>> If this works, then it would be another nice C++ification to see
>> throughout the codebase.
>>
>> Cheers!
>> Daniel
>>
> reinterpret_cast is already used for conversion between different
> levels of the GObject inheritance hierarchy, e.g. in the gobj()
> methods generated by _CLASS_GOBJECT, _CLASS_INTERFACE and
> _CLASS_GTKOBJECT. But it's not used consistently in other situations.
> I see no harm in using it consistently.
>
> Kjell
Clarification: reinterpret_cast is not used consistently in other
situations for conversion between different levels of the GObject
inheritance hierarchy. I'm in favor of reinterpret_cast for such
conversions. Other conversions should be judged separately from case to
case. And static_cast or dynamic_cast is preferable where applicable.

Kjell
_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Loading...