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);
}
<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