C++ Logo

std-proposals

Advanced search

[std-proposals] static_cast should never have been allowed to downcast

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Wed, 21 Jan 2026 12:57:11 +0000
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.

When I'm using 'static_cast' with classes in my own code, in order to
avoid a downcast, I use my own 'static_upcast' defined as follows:

  template<class Derived, class Base>
  concept derived_fromCV = is_base_of_v<Base, Derived> &&
is_convertible_v<Derived*, Base*>;

  template<class To, class From>
  requires is_lvalue_reference_v<To> && (!is_reference_v<From>)
           && derived_fromCV< From, remove_reference_t<To> >
  [[nodiscard]] constexpr To static_upcast(From &arg) noexcept
  {
    return static_cast<To>(arg);
  }

This prevents me from doing a dodgy down-cast, which is a necessary
precaution in my implementation of chimeric_ptr. Note that I use my
own 'derived_fromCV' instead of 'std::derived_from' to avoid a
const/volatile violation.

static_cast should never have been allowed to perform downcasts, and
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

Received on 2026-01-21 12:57:25