1

As the title says, if I cast a pointer to a base class, to a derived class, when the pointer is null, is it a safe operation from the point of view of the C++11/C++14 standard?

struct base
{
   virtual ~base() = default;
};

struct derived : base {};

struct wrapper
{
   using allowed_derived_t = derived;
   base* base_ptr = nullptr;

   void set_ptr(base* ptr)
   {
       if (!dynamic_cast<allowed_derived_t*>(ptr))
          throw std::logic_error("Check your user code");

      base_ptr = ptr;
   }

   allowed_derived_t* ptr() const
   { return static_cast<allowed_derived_t*>(base_ptr); }
};

Is it the ptr() method safe, if I call it before calling set_ptr? Because, before setting the pointer, the base_ptr is not of the required type (allowed_derived_t), however, the dynamic pointed-to object isn't either of the wrong type (because there's no pointed-to object).

What does the standard say in that situation?

ABu
  • 10,423
  • 6
  • 52
  • 103

2 Answers2

6

All well-formed pointer-to-pointer casts guarantee that null pointer of source type is safely converted to a null pointer of target type.

For dynamic_cast it is stated in

5.2.7 Dynamic cast

4 If the value of v is a null pointer value in the pointer case, the result is the null pointer value of type T.

For static_cast it is stated in

5.2.9 Static cast

11 [...] The null pointer value (4.10) is converted to the null pointer value of the destination type.

Similar guarantees are provided by all other casts.

Community
  • 1
  • 1
AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
1

static_cast checks if the conversion is valid at compile time, thus the runtime value of the casted pointer doesn't play any role.

So it's safe, a nullptr will result in a nullptr at runtime.

As much that's true for any other type of cast.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • 1
    You did not hit the point, although the conclusion is correct. In the cast of multiple inheritance, `static_cast` can be an arithmetic operation. So a pointer value of (say) 0x10000 could become 0xFFFC. Actually a runtime check is necessary to make `nullptr` still a `nullptr` in such casts. Compilers potentially need to insert such checks. – Yongwei Wu May 14 '20 at 07:25