Date: Sun, 27 Nov 2022 00:01:11 +0000
Hello Frederick,
After reading your proposal, I tend to agree with Arthur that this can
mostly be accomplished without language changes. The only inherent
"compiler magic" I see in your proposal is the "->" operator on the
chimeric pointer, which I wouldn't know how to implement in the current
language. An alternative which also solves any potential ambiguity is to be
more explicit by using a cast member or free function (as<As>() member in
my example below).
You can implement the chimeric pointer to store the pointer as void* and
validate the type during construction and access:
template<class... Bases>
class chimeric_ptr {
void* raw_;
public:
template<class T>
requires ((std::is_base_of_v<Bases, T> && ...))
/* implicit */ chimeric_ptr(T* obj): raw_(obj) {}
template<class As>
requires ((std::is_same_v<Bases, As> || ...))
As* as() {
return static_cast<As*>(raw_);
}
};
This way, you can safely cast your pointer to any of the required base
classes, and you cannot construct an invalid chimeric_ptr instance. The
static_cast from void to As is safe because of the validation during
construction and restriction on the template parameter of as. And it's
sizeof(void*) because it *is* a void*. You can pick the constructor's
condition to be either is_base_of_v or is_convertible_v based on need, but
I think is_base_of is a better fit for the use case you presented.
I wrote up the demo in Compiler Exporer that includes your example usage
here: https://godbolt.org/z/4q1GjWGoW
Let me know if I'm missing anything here.
Darius
On Fri, Nov 25, 2022 at 7:16 PM Gergely Nagy via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> The solution, while templated, syntactically very similar to what the OP
> proposed.
>
> On Fri, Nov 25, 2022, 20:09 Thiago Macieira via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> On Friday, 25 November 2022 09:27:24 PST Gergely Nagy via Std-Proposals
>> wrote:
>> > Hey Thiago, have you checked my concept based solution above?
>>
>> I did. That's a separate solution but is still a template. TBH, I like
>> yours
>> more, but Frederick's request has merit too. I don't think it's enough to
>> warrant a Standard Library feature, and thus definitely not for a Core
>> Language
>> one, but it can be solved within a regular library, such as wx itself. I
>> just
>> wanted to point out it is possible and, quite frankly, probably would be
>> exactly as costly as the Standard feature would end up being.
>>
>> In particular, I don't buy the arguments against the template. You can
>> avoid
>> the problems with static members by moving them to non-template functions
>> that
>> get used in the template, offloading portions of the work based on the
>> characteristics of the templated argument. That's where your concepts
>> solution
>> works.
>>
>> The other part is that accessing two base sub-objects that don't form a
>> class
>> itself indicates a design issue. If this use of a text entry and a
>> control is
>> common, the hierarchy should have been as suggested by Arthur:
>>
>> struct TextCtrl : Control, TextEntry {};
>> struct TextCtrl1 : TextCtrl {}; // CHANGED!!
>> struct TextCtrl2 : TextCtrl {}; // CHANGED!!
>>
>> And if it is not common, then I don't think we need a Standard feature
>> for.
>> --
>> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
>> Software Architect - Intel DCAI Cloud Engineering
>>
>>
>>
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
After reading your proposal, I tend to agree with Arthur that this can
mostly be accomplished without language changes. The only inherent
"compiler magic" I see in your proposal is the "->" operator on the
chimeric pointer, which I wouldn't know how to implement in the current
language. An alternative which also solves any potential ambiguity is to be
more explicit by using a cast member or free function (as<As>() member in
my example below).
You can implement the chimeric pointer to store the pointer as void* and
validate the type during construction and access:
template<class... Bases>
class chimeric_ptr {
void* raw_;
public:
template<class T>
requires ((std::is_base_of_v<Bases, T> && ...))
/* implicit */ chimeric_ptr(T* obj): raw_(obj) {}
template<class As>
requires ((std::is_same_v<Bases, As> || ...))
As* as() {
return static_cast<As*>(raw_);
}
};
This way, you can safely cast your pointer to any of the required base
classes, and you cannot construct an invalid chimeric_ptr instance. The
static_cast from void to As is safe because of the validation during
construction and restriction on the template parameter of as. And it's
sizeof(void*) because it *is* a void*. You can pick the constructor's
condition to be either is_base_of_v or is_convertible_v based on need, but
I think is_base_of is a better fit for the use case you presented.
I wrote up the demo in Compiler Exporer that includes your example usage
here: https://godbolt.org/z/4q1GjWGoW
Let me know if I'm missing anything here.
Darius
On Fri, Nov 25, 2022 at 7:16 PM Gergely Nagy via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> The solution, while templated, syntactically very similar to what the OP
> proposed.
>
> On Fri, Nov 25, 2022, 20:09 Thiago Macieira via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> On Friday, 25 November 2022 09:27:24 PST Gergely Nagy via Std-Proposals
>> wrote:
>> > Hey Thiago, have you checked my concept based solution above?
>>
>> I did. That's a separate solution but is still a template. TBH, I like
>> yours
>> more, but Frederick's request has merit too. I don't think it's enough to
>> warrant a Standard Library feature, and thus definitely not for a Core
>> Language
>> one, but it can be solved within a regular library, such as wx itself. I
>> just
>> wanted to point out it is possible and, quite frankly, probably would be
>> exactly as costly as the Standard feature would end up being.
>>
>> In particular, I don't buy the arguments against the template. You can
>> avoid
>> the problems with static members by moving them to non-template functions
>> that
>> get used in the template, offloading portions of the work based on the
>> characteristics of the templated argument. That's where your concepts
>> solution
>> works.
>>
>> The other part is that accessing two base sub-objects that don't form a
>> class
>> itself indicates a design issue. If this use of a text entry and a
>> control is
>> common, the hierarchy should have been as suggested by Arthur:
>>
>> struct TextCtrl : Control, TextEntry {};
>> struct TextCtrl1 : TextCtrl {}; // CHANGED!!
>> struct TextCtrl2 : TextCtrl {}; // CHANGED!!
>>
>> And if it is not common, then I don't think we need a Standard feature
>> for.
>> --
>> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
>> Software Architect - Intel DCAI Cloud Engineering
>>
>>
>>
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
Received on 2022-11-27 00:01:25