C++ Logo

std-proposals

Advanced search

[std-proposals] dynamic_cast<void*>(void*)

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Mon, 26 Feb 2024 10:22:14 +0000
With regard to dynamic_cast'ing to a void*, the Standard currently reads:


    7.6.1.7 Dynamic cast
    1. The result of the expression dynamic_cast<T>(v) is
       the result of converting the expression v to type T.
    5. Otherwise, v shall be a pointer to or a glvalue of a
       polymorphic type.
    7. If T is “pointer to cv void”, then the result is a pointer
       to the most derived object pointed to by v.

So let's consider the following function:

    void *Func(std::ostream *const v)
    {
        return dynamic_cast<void*>(v);
    }

On an x86_64 computer running Linux or macOS, using the GNU g++
compiler, this becomes:

    test rdi,rdi
    je the_pointer_is_null
    mov rax,QWORD PTR [rdi]
    add rdi,QWORD PTR [rax-0x10]
    mov rax,rdi
    ret
the_pointer_is_null:
    xor eax,eax
    ret

If we remove the code that allows for 'v' to be a nullptr, it's
simplified further to:

    mov rax,QWORD PTR [rdi]
    add rdi,QWORD PTR [rax-0x10]
    mov rax,rdi
    ret

This assembler can be converted back into C++ as follows:

    void *Func(void *const v)
    {
        auto const p_vtable = *static_cast<uintptr_t**>(v);
        auto const top_offset = p_vtable[-2];
        return static_cast<char*>(v) + top_offset;
    }

The implementation of this function is the same no matter what the
type of 'v' is -- so long as it's a polymorphic type. In fact, it can
be rewritten as follows:

    void *Func(void *const v)
    {
        struct Dummy { virtual ~Dummy(void){} };
        return dynamic_cast<void*>( static_cast<Dummy*>(v) );
    }

The point I want to make here is as follows: So long as 'v' points to
a polymorphic type, it is not necessary to know that that type is.
Therefore I think that the functionality of 'dynamic_cast' should be
expanded to allow 'v' to be a pointer to void -- with the note that
the behaviour is undefined if 'v' points to a non-polymorphic object.

Received on 2024-02-26 10:22:27