-
-
Notifications
You must be signed in to change notification settings - Fork 706
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
Fix #13872 #2804
Fix #13872 #2804
Conversation
|
I think this is a terrible hack, and some containers don't even have length, like linked lists; this patch would make it so that
|
|
First about the hack. Yes it is a terrible hack, but I is no problem that not all container support length nor that's is kind of arbitrary. It only has to work with std.containers and it works with all containers currently supported. Second make's description says, that make should eliminate construction differences between class-based and struct-based containers. As far as it stands now, it does not. Third: I only made this patch, because I wanted to provide a example on how to construct an Array!(Array!int). Every approach I used was too embarrassing to put into the documentation. "You know, because make returns something like a null reference you'll have to add an element and remove it again, to force the payload to be initialized, after that Array will have proper reference semantics.". I don't like this either, but we really have to do something about this. This is the best way, IMO. |
|
Why can't we just add a way to make an empty container to the actual containers? I can understand why the default init would be a null container, but making an empty one is pretty fundamental.
But it should work with other containers too, so we either have to document setting length as the official way to do this, or (my preference) add a less obscure primitive to do it. |
I'm not so sure, that std.container.make is meant to be used with user defined containers. It is there to hide implementation details after all. As far as I understand, the primitive to create an empty container is make. I have no hard feelings about this, though we should prefer the hacky solution, that our users cannot see over an more complicated interface. Changing the documentation to make arbitrary behaviour correct by definition, is a even worse solution. |
I'm not so sure either, and to be honest I've never used std.container. Maybe @andralex can comment on this? |
|
I don't think it's a hack - indeed it was the intent of make in the first place, I can't believe I missed that. Creating a null container is readily doable by means of |
|
|
|
What about calling the constructor with |
|
@JakobOvrum oh I see, thanks. Perhaps it would make sense to require a primitive at the container level. |
|
(though forcing a copy construction is also interesting) |
|
@yebblies Why should this be more reliable? alias T = Array!int; This will call the constructor taking Stuff, which will call reserve(0), which in turn initializes the payload, which is as arbitrary as setting length to zero directly. Or does it call the constructor taking U[] values...? There is nothing in the docs of std.container that would forbid a user defined container to if(values.length == 0) return; at the top of the constructor, making it exactly as unreliable as any other method. Besides: https://issues.dlang.org/show_bug.cgi?id=13919 Does make even have to work with anything outside of std.container? |
|
We could alter the spec so that calling the constructor with an empty array guarantees the container will be initialized, is what I mean. I'm not so sure that we can rely on setting length to zero to do that, it seems much more reasonable that setting length to zero could completely wipe the container (or it might be impossible for some containers.) I think that expecting that calling the constructor with an array that may or may not be empty to always initialize is reasonable.
This is what I was hoping @andralex could answer. |
Not for the time being. |
The proposed solution doesn't work with all standard containers, it only works with containers that have length (and settable length, at that). That already precludes the standard There's also no guarantee that setting length to 0 causes identity. I think it's clear that we need to either amend an existing primitive or create a new one to facilitate this, like @yebblies' idea. |
You're right. Actually I thought currently Array were the only struct based container. So, how to do it? |
|
Pass an empty array to the array constructor. |
|
I've added two additional tests for SList and DList and now an empty container is constructed by passing an empty array. I'm using a static one though to avoid an allocation. I hope that flies. |
|
ping |
| @@ -30,7 +30,22 @@ if (is(T == struct) || is(T == class)) | |||
| T make(Args...)(Args arguments) | |||
| if (is(T == struct) && __traits(compiles, T(arguments))) | |||
| { | |||
| return T(arguments); | |||
| auto result = T(arguments); | |||
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.
Where is "result" used in this function?
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.
Thanks, will fix.
eb58460 to
63924dd
Compare
|
The description of the construction primitive |
std.container.make!(Array!T) now returns a reference to an actual container, not a 'null reference' that initializes itself upon use.
|
Ping. Dunno if everyone gets a message if I just rebase. |
Nobody gets a message. |
|
LGTM. @yebblies? |
|
Auto-merge toggled on |
std.container.make!(Array!T) now returns a reference
to an actual container, not a 'null reference' that
initializes itself upon use.
A more elegant solution would be to provide an overload for Array, but if I define it in std/container/array.d it will issue a conflict (even if the template is more specialized) and to do it in std/container/util.d would require to import std.container.array and I am not sure if we want that, because of the ongoing effort to decouple the imports in phobos. Regardless, setting length to 0 shouldn't be a problem for any struct based container constructed without arguments.