C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Chimeric Pointer

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Sun, 27 Nov 2022 11:28:52 +0000
On Sun, Nov 27, 2022 at 2:40 AM Thiago Macieira via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> Think of two base sub-objects in two different classes with different offsets:
>
> class wxControl1: public wxTextEdit, public wxControl { ... };
> class wxControl2: public wxControl, public wxTextEdit { ... };
>
> You must either store the actual bases or have a way to restore the offsets
> from the top-of-object void pointer. That's not static_cast.
>
> It can be a dynamic_cast, but not on a void * because the address of the
> vtable pointer isn't know there either.


I have made additions to Darius's code to make it work properly with
complex cases of virtual inheritance. See here:

    https://godbolt.org/z/3qYjhdxxs

Lines 18, 28 and 35 are the lines of interest.

I've copy-pasted the code here:

// BEGIN Chimeric pointer implementation
#include <type_traits> // is_convertible_v
#include <tuple> // tuple

// I have chosen to use 'is_convertible_v' instead of "is_base_of_v"
for two reasons:
// (1) The latter would accommodate non-public inheritance (we don't want that)
// (2) Currently the C++ programming language only allows Derived class pointers
// to be converted to Base class pointers. However in the future, maybe the
// Standard will be changed to allow some other kind of implicit conversion.
// I want the chimeric pointer to be versatile and future-proof so I'm
// choosing 'is_convertible_v' over the alternatives of "is_base_of_v" or
// 'derived_from'.

template<class... Bases>
class chimeric_ptr {
protected:

    std::tuple<Bases*...> pointers;

public:

    template<class T>
    requires ((std::is_convertible_v<T*, Bases*> && ...))
    /* implicit */ chimeric_ptr(T *const obj)
    {
        // The fold expression on the next line sets
        // each of the pointers in the tuple
        ((std::get<Bases*>(pointers) = obj), ...);
    }

    template<class As>
    requires ((std::is_same_v<Bases, As> || ...))
    As *as(void)
    {
        return std::get<As*>(pointers);
    }
};
// END Chimeric pointer implementation

// Example
struct Control {
    virtual ~Control() = default;

    void Refresh();
    void SetBackgroundColour(const char*);
};

struct TextEntry {
    virtual ~TextEntry() = default;

    void SetValue(const char*);
};

struct TextControl: Control, TextEntry {
    virtual ~TextControl() = default;
};

struct Combo: Control, TextEntry {
    virtual ~Combo() = default;
};

void Red( chimeric_ptr<Control,TextEntry> p )
{
    p.as<Control>()->SetBackgroundColour( "red" );
    p.as<TextEntry>()->SetValue("pending");
    p.as<Control>()->Refresh();
}

// Invocations
void UseRed(TextControl* textCtrl, Combo* combo)
{
    Red(textCtrl);
    Red(combo);
}

Received on 2022-11-27 11:29:02