godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
91.18k stars 21.2k forks source link

`RBMap<StringName, V>` doesn't have unique order or it is meaningless #79596

Closed TokageItLab closed 1 year ago

TokageItLab commented 1 year ago

Godot version

4.1

System information

Any

Issue description

Perhaps because the entity of StringName is a memory address, the order of StringName is not unique when it is used as a key in RBMap.

RBMap<StringName, V> is used in several classes/places:

There are two ways to solve this problem, and we should choose one of them depends on each case:

Steps to reproduce

If you run the following code anywhere, you can see that the order changes each time Godot is launched.

RBMap<StringName, int> rbm;
rbm.insert(StringName("a"), 0);
rbm.insert(StringName("b"), 1);
rbm.insert(StringName("c"), 2);
rbm.insert(StringName("d"), 3);
rbm.insert(StringName("e"), 4);
String concat;
for (const KeyValue<StringName, int> &E : rbm) {
    concat += "[" + String(E.key) + ",";
    concat += itos(E.value) + "]";
}
WARN_PRINT(concat);

Minimal reproduction project

RBMap is a C++ class and is not exported to gdscript, so there is no project. Run the above code in any .cpp.

AThousandShips commented 1 year ago

StringName compares by pointer, as you mentioned the appropriate way to do that is to use StringName::AlphCompare, the reason why StringName compares this way is performance, and the order will be stable, though newer names might end up before older ones depending on allocations

TokageItLab commented 1 year ago

Closed by #79595.