Conversation
There was a problem hiding this comment.
I have some thoughts about this.
First off, I think this is generally a great idea.
What we have currently is the implicit copy constructor, which is very disingenuous about its real cost:
// Whoops, actually extremely expensive, because all strings are copied!
HashSet<String> set = p_hash_set;It would already be much better to make copy constructors explicit only:
// Now it's somewhat clear we're making a new hash set.
HashSet<String> set = HashSet(p_hash_set);However, I do prefer the .duplicate you suggest, even if it is a little non-C++ style.
Still, our priority for things like this needs to be consistency. If we're adding .duplicate, we need to remove the copy constructor. Otherwise, both APIs will be used, and it won't be clear which function is preferred.
Likewise, we can't just add .duplicate to one or two isolated container types. Otherwise, people will always have to guess if it's "one of those containers with .duplicate" or "one of those other containers with a copy constructor". We'd need to add them to all containers, and remove the copy constructors, in one fell swoop.
All of this makes this a bit bigger than a few innocuous lines, and it would need to be agreed on by the core team, in my opinion.
There is already a similar API in Vector<> for duplicating those.
That's a good point. I think the reason it exists for Vector is that it's exposed to GDScript (and it's probably in the codebase for consistency). It acts the same as the copy constructor from C++.
However, in GDScript it acts different from the copy constructor, because regular assignment references the original array, rather than making a CoW copy (like .duplicate). This creates a need for .duplicate, which likely prompted this function to be added in the first place.
|
@Ivorforce What is the harm in adding the API before removing the copy constructor? It would be nice to have both existing in the codebase so that third-party modules can support multiple Godot versions. I'm not saying we should delay removing the copy constructor for that use case, I'm just saying I don't think that should hold everything up. Plus, this way, it is easier to cherry-pick the addition of the functions to older branches if needed. As for confusion on which to use, if the plan is to remove one, then... it doesn't matter, we'll migrate them all one way or another, since that migration will be forced to happen when removing the copy constructors. We could definitely add the function to other container types, yeah. Which ones did you have in mind? |
67b7358 to
9fe6ac4
Compare
|
This PR's deprecation of the implicit duplication has caught a bug in the Wayland code: #101774 (comment) I suppose that's another argument in favor of merging this in sooner rather than later :) |
|
@aaronfranke I think for now, we should simply make the existing constructor While On the other hand, making the existing constructor |
|
@Ivorforce Attempting to do that has revealed a new problem. In functions like Another thing: Intellisense can find all uses of a function, but doing the same with constructors is much harder. |
Yea... this is a problem we'll have to deal with eventually anyway.
I don't think C++ can generate a correct trivial copy constructor for
That may be true, and it's a good argument for the |
9fe6ac4 to
3c4fb60
Compare
3c4fb60 to
293ea08
Compare
293ea08 to
2d8581f
Compare
2d8581f to
1811bfe
Compare
1811bfe to
689c2ce
Compare
Follow-up to #106537 (comment)
HashSet has a copy constructor, but it's not obvious whether the constructor is truly copying the underlying data just from reading the usage. This makes the intent clearer, at the cost of adding a very small function to HashSet. There is already a similar API in
Vector<>for duplicating those.