Date: Wed, 21 Jan 2026 14:23:13 +0100
Hi,
On Wed, Jan 21, 2026 at 1:57 PM Frederick Virchanza Gotham via
Std-Proposals <std-proposals_at_[hidden]> wrote:
> Before I begin, I realise that static_cast can cause UB with
> intrinsics, for example:
>
> char a;
> double &d = *static_cast<double*>( static_cast<void*>(&a) );
> d = 0.0;
>
> But in this post I'm talking specifically about classes. We can use
> 'static_cast' to convert from a derived class to a base:
>
> Base *b = static_cast<Base*>( &derived );
>
> or more simply:
>
> Base *b = &derived;
>
> If you imagine this as a UML class diagram, you'll have a box for
> Base, and then below it you'll have a box for Derived. You're
> converting from Derived to Base, so the movement is going upwards, and
> so we call it an upcast.
>
> Converting from Base to Derived is called a downcast, and it can cause UB:
>
> struct Base { int a; };
> struct Derived : Base { int b; };
> Base var;
> Derived &derived = static_cast<Derived&>( var );
> derived.b = 666;
>
> This should never have been made possible with 'static_cast' -- there
> should have been a different kind of cast operator for this purpose.
>
static_cast was introduced at a time when only one type of cast existed.
You either did or didn't cast, and if you did cast it would represent an
increasingly blunt hammer to make it fit into the target type. Having the
ability to specify "Only the safe-ish kind of conversion" with static_cast
was a huge improvement, and even then it got lots of bad press by the
people teaching me C++. If it had proposed ~20 different casts for the
different kinds of conversions back then, it would've been laughed out of
the room.
That said, we should have those casts added now / soon, because they have
safety implications, and we should work on making it possible for users to
exclude the less safe casts from their code.
... in order to deal with this issue, I think the following should happen:
>
> C++29: Using static_cast for downcasts should be marked
> deprecated, and a compiler warning should be issued wherever
> static_cast is used for purpose, and the compiler should provide the
> alternative 'static_downcast'.
> C++32: static_cast forces a compiler error when used for a
> downcast, and so you must use static_downcast
>
Lots of code exists that uses static_cast in its intended way and that have
zero bugs with it. As such I don't think "deprecating" static_cast will
ever happen.
That said, it would be great if we could add the more restricted casts,
with a good rationale why they are now actually correct, and then create a
profile that disallows the older ones - all of the ones identified in that
paper as being now superfluous and dangerous.
Note that we already get saturate_cast in C++26, which is one of those.
On Wed, Jan 21, 2026 at 1:57 PM Frederick Virchanza Gotham via
Std-Proposals <std-proposals_at_[hidden]> wrote:
> Before I begin, I realise that static_cast can cause UB with
> intrinsics, for example:
>
> char a;
> double &d = *static_cast<double*>( static_cast<void*>(&a) );
> d = 0.0;
>
> But in this post I'm talking specifically about classes. We can use
> 'static_cast' to convert from a derived class to a base:
>
> Base *b = static_cast<Base*>( &derived );
>
> or more simply:
>
> Base *b = &derived;
>
> If you imagine this as a UML class diagram, you'll have a box for
> Base, and then below it you'll have a box for Derived. You're
> converting from Derived to Base, so the movement is going upwards, and
> so we call it an upcast.
>
> Converting from Base to Derived is called a downcast, and it can cause UB:
>
> struct Base { int a; };
> struct Derived : Base { int b; };
> Base var;
> Derived &derived = static_cast<Derived&>( var );
> derived.b = 666;
>
> This should never have been made possible with 'static_cast' -- there
> should have been a different kind of cast operator for this purpose.
>
static_cast was introduced at a time when only one type of cast existed.
You either did or didn't cast, and if you did cast it would represent an
increasingly blunt hammer to make it fit into the target type. Having the
ability to specify "Only the safe-ish kind of conversion" with static_cast
was a huge improvement, and even then it got lots of bad press by the
people teaching me C++. If it had proposed ~20 different casts for the
different kinds of conversions back then, it would've been laughed out of
the room.
That said, we should have those casts added now / soon, because they have
safety implications, and we should work on making it possible for users to
exclude the less safe casts from their code.
... in order to deal with this issue, I think the following should happen:
>
> C++29: Using static_cast for downcasts should be marked
> deprecated, and a compiler warning should be issued wherever
> static_cast is used for purpose, and the compiler should provide the
> alternative 'static_downcast'.
> C++32: static_cast forces a compiler error when used for a
> downcast, and so you must use static_downcast
>
Lots of code exists that uses static_cast in its intended way and that have
zero bugs with it. As such I don't think "deprecating" static_cast will
ever happen.
That said, it would be great if we could add the more restricted casts,
with a good rationale why they are now actually correct, and then create a
profile that disallows the older ones - all of the ones identified in that
paper as being now superfluous and dangerous.
Note that we already get saturate_cast in C++26, which is one of those.
Received on 2026-01-21 13:23:27
