New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add destruct
function
#929
Conversation
Note, that it destructs a given object, but not something it references. | ||
So to destruct a class instance, use $(D object.finalizeClassInstance). | ||
*/ | ||
void destruct(T)(ref T t, bool resetInitialState = true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make this auto ref
and make it so no assignment is done if the parameter isn't assignable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, you are proposing to support this:
import std.typecons: destruct;
struct S { ... }
S f() { ... }
void main()
{
destruct(f());
}
Practical use cases?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Practical use cases?
Why on earth should you have to be destroying a variable? destroy
certainly doesn't require it. Being able to set a reference or pointer to null
after destroying what it points to makes sense, but why restrict it to only work with lvalues? Limiting it to ref
is artificially restrictive, since the fact that you're destroying something doesn't have anything to do with whether it's an lvalue or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why on earth should you have to be destroying a variable? destroy certainly doesn't require it. Being able to set a reference or pointer to null after destroying what it points to makes sense, but why restrict it to only work with lvalues? Limiting it to ref is artificially restrictive, since the fact that you're destroying something doesn't have anything to do with whether it's an lvalue or not.
When we are destructing something by hands, it means that we have a reference to it which scope lasts longer than we need. And if we have no variable, we have no scope problems: just write { f(); }
instead of destruct(f());
.
Possibly I'm loosing some useful cases, so I'm asking again for practical use cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All it takes is having what you're looking to destroy be returned from a function (e.g. the object that had ownership of it is handing it off to you). If you force ref
, then that would have to be assigned to a variable instead of just fed directly to destroy
/destruct
. Regardless, requiring ref
restricts it to lvalues when there's no reason not to work with rvalues`.
And I still want to know why this function is being created at all. This is what destroy
is for.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First, why haven't you already discussed you no-ref proposal for current object.destroy
?
Second, I don't understand it at all:
All it takes is having what you're looking to destroy be returned from a function (e.g. the object that had ownership of it is handing it off to you). If you force ref, then that would have to be assigned to a variable instead of just fed directly to destroy/destruct.
Why not just give an example?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just give an example?
How is that not an example. If you have an object which owns an object, and it has a function which relinquishes ownership of that object to the caller and returns it, then if destruct
takes ref
, then you'd have to assign it to a variable first just to destroy it. e.g.
auto obj = owner.relinquishOwnership(key);
destruct(obj);
instead of
destruct(owner.relinquishOwnership(key));
Regardless, unless specifically requiring an lvalue buys you something (and I don't see why it would), then I see no reason to restrict the function to lvalues. Just use auto ref
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I already wrote it ( just write { f(); }
instead of destruct(f());
) I still do not understand what do you want.
Probably, you misunderstand the situation.
If you need a statement, you do this:
// statements
destruct(owner.relinquishOwnership(key)); // your variant
{ owner.relinquishOwnership(key); } // variant without `destruct`
// statements
If you need an expression, you do this:
// your variant
(/* expressions */ , destruct(owner.relinquishOwnership(key)), /* expressions */ ) ;
// variant without `destruct`
(/* expressions */, { owner.relinquishOwnership(key); }(), /* expressions */ ) ;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@alexrp, can you post you opinion here too, please?
Why do we need this? Isn't this what |
I wrote my reasons to supersede |
You're referencing the wrong pull (phobos pull 344 instead of druntime), it should be this: dlang/druntime#344 |
@denis-sh: I doubt your assumption that »druntime isn't a place for template code at all« – how did you come to this conclusion? |
Almost every template code requires |
I think this function is unnecessary and dangerous. Will close this now. |
Really? How ironic... This pull contains the only function usable for object destruction and it is rejected. |
@klickverbot AFAIK presence of templates inside a library prevents from making it a dynamic - that's why D, unlike C statically links to its runtime library and that's why phobos static library includes druntime which makes D binaries so bloated. |
Templates do not prevent a library from being dynamic. It's just that the templates themselves aren't really part of the dynamic library, because they're instantiated when used, and there's no way to include every possible instantiation in the dynamic library. C++ is in exactly the same boat. Templates must go in header files, and it's mostly what's in the source files which end up in the library, whereas the header files get recompiled every time that they're included. The fact that D statically links to its runtime stems from the fact that the runtime doesn't support dynamic libraries yet. Once it does, it will likely be dynamically linked rather than statically linked. Templates have nothing to do with it. |
According to this thread: The bug is in phobos: Apparently, when being destroyed, |
@monarchdodra, could I ask you for help in inclusion in Phobos a proper implementation of functions for user-defined lifetime from unstd.lifetime? It is not generally useful stuff for an averege user so I don't expect any feedback at NG but it's critical for e.g. collections and typed manual memory allocators. So I'll be happy to be able to merge this facility. Anyway thanks for comment. In ancient times I tried to add stuff to Phobos "I think this function is unnecessary and dangerous" was a common answer and all my arguments was considered insufficient. |
[EDITED]
We definitely need a function for object destruction which do exactly the same a compiler do in a case an object goes out of scope. First of all, it is needed for template programming:
An example of usage is an analog of a struct with manual memory management. Let us want to destruct such struct-analog:
Also note, that druntime isn't a place for template code at all so proposed
destruct
function should definitely be in phobos.Not sure about module where to place
destruct
.Requires pull #928, assumes pull dlang/druntime#344.