Date: Mon, 15 Feb 2021 18:10:12 +0100
Generally, parametric destrucor syntax would need a "deinitialization
list", symmetrically to constructor. I am not sure about details, but
this would looks like:
//---
class cDerivedC : public cBaseC {
std::string a; // on deinitialization list - handled manually,
no auto-destructor
std::string b; // on list with parameter - call delegated to its
own parametric destructor
std::string c; // not on list - normal (non parametric) automatic
destructor
public:
~cDerivedC (cDerivedSink* sink)
baseC( (cBaseSink*)sink ),
a,
b(sink->b)
{ sink->TakeOverA(a);}
};
//------
Then "destructive move", aka "DestructorConstructor", will be a special
case of this general semantic.
And default destructive move will have all those auto-matching correct
fields capabilities that you propose, like moving field "a" to
"target->a", initializing base class of target from base class of source
itd.
On 2021-02-13 01:08, Edward Catmur wrote:
> OK, I can see that destructor syntax is superior for that case.
>
> What about the issue of subobjects, though? Do those have their usual
> destructors called or is there opportunity to override that? In any
> case, in what order do destructors get called in - is it the usual
> order (backwards) or in reverse (forwards)?
>
> And what if you want to destructive move not into a region of storage
> but into a prvalue? Constructor syntax makes that easy to implement;
> destructor syntax would require considerable gymnastics from the compiler.
>
>
> On Fri, Feb 12, 2021 at 7:56 PM Maciej Polanski via Std-Discussion
> <std-discussion_at_[hidden]
> <mailto:std-discussion_at_[hidden]>> wrote:
>
> I can see a problem with constructor approach. There will be:
>
> 1. Zero-abstraction-cost way for data in - normal constructor,
> taking e.g. naked pointer
>
> 2. Zero-abstraction-cost way of relocating data - e.g.
> "A(std::relocates, A* ptr)"
>
> 3. But it lacks zero-abstraction-cost way of data out - at the
> end, there is always a need to set pointers to zero and call
> destructor to do nothing
>
>
> So any constructor approach will be somewhat incomplete, not
> covering whole lifetime of data.
>
> The only way to elide spare destructor calls I can imagine, is to
> create kind of "moving out destructor", that replaces default one.
> So that's why I prefer destructor :)
>
>
> PS. Seems I have some problem with discussion list, I hope this
> message will be delivered correctly.
>
>
> On 2021-02-12 18:41, Edward Catmur wrote:
>> That's a very interesting use case, but it could easily be
>> accommodated in other proposals, e.g. in N4158 by allowing the
>> two arguments to be of different types.
>>
>> The reason I think that a constructor syntax is to be preferred
>> is that it's more difficult to set up class invariants than it is
>> to leave a class's members in a state where the destructor can be
>> elided without a leak. For instance, what happens if someone adds
>> a std::string member to your type? - under a constructor-style
>> proposal, a member that is not explicitly initialized in the
>> mem-initializer-list can be automatically initialized by
>> destructive move from the corresponding member on the other
>> instance (of the same type).
>>
>> On Fri, Feb 12, 2021 at 12:43 PM Maciej Polanski via
>> Std-Discussion <std-discussion_at_[hidden]
>> <mailto:std-discussion_at_[hidden]>> wrote:
>>
>>
>> On 2021-02-11 20:02, Edward Catmur via Std-Discussion wrote:
>> > This would operate very similarly to the current proposal,
>> but with
>> > the possibly unintuitive difference that the new object is
>> being
>> > passed as the parameter, so that e.g. ~c(x.c) initializes
>> x.c with the
>> > value of c. Furthermore, it would require re-inventing
>> syntax to allow
>> > for move construction of subobjects.
>>
>> While approaches "Constructor that destructs its argument" and
>> "Destructor that constructs its argument" seems to be just
>> symmetrical,
>> my DestrcutorConstructor would have one more feature: it allows
>> "destructing move" depositing object's data in object of
>> other class, or
>> even a function.
>>
>> So without judging if this is worth efforts or not, I'd like to
>> highlight this part of my proposal:
>>
>> //------
>> // class to receive data from object being deleted
>> class cDataSink {
>> public:
>> TakeOverData(cSomeData*);
>> }
>>
>> // class that can be deleted with real zero-additional-cost
>> transfer of
>> data:
>> class C {
>> cSomeData *pDdata;
>>
>> public:
>> ~C(cDataSink* sink) { sink->TakeOverData(data); } // <-
>> DepositingDestructor here
>> ~C() { delete pData; } //
>> Normal
>> destructor
>> };
>> //------
>>
>> Regards,
>> Maciej
>>
>> --
>> Std-Discussion mailing list
>> Std-Discussion_at_[hidden]
>> <mailto:Std-Discussion_at_[hidden]>
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>> <https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion>
>>
> --
> Std-Discussion mailing list
> Std-Discussion_at_[hidden]
> <mailto:Std-Discussion_at_[hidden]>
> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
> <https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion>
>
list", symmetrically to constructor. I am not sure about details, but
this would looks like:
//---
class cDerivedC : public cBaseC {
std::string a; // on deinitialization list - handled manually,
no auto-destructor
std::string b; // on list with parameter - call delegated to its
own parametric destructor
std::string c; // not on list - normal (non parametric) automatic
destructor
public:
~cDerivedC (cDerivedSink* sink)
baseC( (cBaseSink*)sink ),
a,
b(sink->b)
{ sink->TakeOverA(a);}
};
//------
Then "destructive move", aka "DestructorConstructor", will be a special
case of this general semantic.
And default destructive move will have all those auto-matching correct
fields capabilities that you propose, like moving field "a" to
"target->a", initializing base class of target from base class of source
itd.
On 2021-02-13 01:08, Edward Catmur wrote:
> OK, I can see that destructor syntax is superior for that case.
>
> What about the issue of subobjects, though? Do those have their usual
> destructors called or is there opportunity to override that? In any
> case, in what order do destructors get called in - is it the usual
> order (backwards) or in reverse (forwards)?
>
> And what if you want to destructive move not into a region of storage
> but into a prvalue? Constructor syntax makes that easy to implement;
> destructor syntax would require considerable gymnastics from the compiler.
>
>
> On Fri, Feb 12, 2021 at 7:56 PM Maciej Polanski via Std-Discussion
> <std-discussion_at_[hidden]
> <mailto:std-discussion_at_[hidden]>> wrote:
>
> I can see a problem with constructor approach. There will be:
>
> 1. Zero-abstraction-cost way for data in - normal constructor,
> taking e.g. naked pointer
>
> 2. Zero-abstraction-cost way of relocating data - e.g.
> "A(std::relocates, A* ptr)"
>
> 3. But it lacks zero-abstraction-cost way of data out - at the
> end, there is always a need to set pointers to zero and call
> destructor to do nothing
>
>
> So any constructor approach will be somewhat incomplete, not
> covering whole lifetime of data.
>
> The only way to elide spare destructor calls I can imagine, is to
> create kind of "moving out destructor", that replaces default one.
> So that's why I prefer destructor :)
>
>
> PS. Seems I have some problem with discussion list, I hope this
> message will be delivered correctly.
>
>
> On 2021-02-12 18:41, Edward Catmur wrote:
>> That's a very interesting use case, but it could easily be
>> accommodated in other proposals, e.g. in N4158 by allowing the
>> two arguments to be of different types.
>>
>> The reason I think that a constructor syntax is to be preferred
>> is that it's more difficult to set up class invariants than it is
>> to leave a class's members in a state where the destructor can be
>> elided without a leak. For instance, what happens if someone adds
>> a std::string member to your type? - under a constructor-style
>> proposal, a member that is not explicitly initialized in the
>> mem-initializer-list can be automatically initialized by
>> destructive move from the corresponding member on the other
>> instance (of the same type).
>>
>> On Fri, Feb 12, 2021 at 12:43 PM Maciej Polanski via
>> Std-Discussion <std-discussion_at_[hidden]
>> <mailto:std-discussion_at_[hidden]>> wrote:
>>
>>
>> On 2021-02-11 20:02, Edward Catmur via Std-Discussion wrote:
>> > This would operate very similarly to the current proposal,
>> but with
>> > the possibly unintuitive difference that the new object is
>> being
>> > passed as the parameter, so that e.g. ~c(x.c) initializes
>> x.c with the
>> > value of c. Furthermore, it would require re-inventing
>> syntax to allow
>> > for move construction of subobjects.
>>
>> While approaches "Constructor that destructs its argument" and
>> "Destructor that constructs its argument" seems to be just
>> symmetrical,
>> my DestrcutorConstructor would have one more feature: it allows
>> "destructing move" depositing object's data in object of
>> other class, or
>> even a function.
>>
>> So without judging if this is worth efforts or not, I'd like to
>> highlight this part of my proposal:
>>
>> //------
>> // class to receive data from object being deleted
>> class cDataSink {
>> public:
>> TakeOverData(cSomeData*);
>> }
>>
>> // class that can be deleted with real zero-additional-cost
>> transfer of
>> data:
>> class C {
>> cSomeData *pDdata;
>>
>> public:
>> ~C(cDataSink* sink) { sink->TakeOverData(data); } // <-
>> DepositingDestructor here
>> ~C() { delete pData; } //
>> Normal
>> destructor
>> };
>> //------
>>
>> Regards,
>> Maciej
>>
>> --
>> Std-Discussion mailing list
>> Std-Discussion_at_[hidden]
>> <mailto:Std-Discussion_at_[hidden]>
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>> <https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion>
>>
> --
> Std-Discussion mailing list
> Std-Discussion_at_[hidden]
> <mailto:Std-Discussion_at_[hidden]>
> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
> <https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion>
>
Received on 2021-02-15 11:10:20