Download

operator== and GetTypeHash() proper implementation

I have a Struct FCombinableKey which contains two Items.
this struct should be used as a Key for Map.

The struct should be equal when the two items are equal, regardless of their order.
This is my struct:



USTRUCT(BlueprintType)
struct FCombinableKey {
GENERATED_BODY()

public:
 UPROPERTY(EditAnywhere, BlueprintReadWrite)
 UItem* ItemA;
 UPROPERTY(EditAnywhere, BlueprintReadWrite)
 UItem* ItemB;

 bool operator== (const FCombinableKey& Other)
 {
  return ((this->ItemA == Other.ItemA) && (this->ItemB == Other.ItemB)) || ((this->ItemA == Other.ItemB) && (this->ItemB == Other.ItemA));
 }
 friend uint32 GetTypeHash(const FCombinableKey& Other)
 {
  return GetTypeHash(Other.ItemA) + GetTypeHash(Other.ItemB);
 }
};


However, A TMap only returns the object if the Combinable Key is completely equal:


unknown.png

Can someone tell me how to fix this?

After some debugging I found out that the Has Value is correct, but the == operator is not being called!

For both Array.Find() and Map.Find() the operator isnt being called

Can’t remember the details of how it works offhand, but I think for blueprints, those C++ methods are unknown and the comparisons will be done via the reflection system by default. Which would be per-property, hence the behaviour.

I think this can be overridden. Have a search in the engine codebase for CppStructOps. It’s a way of specifying custom C++ behaviour that the reflection system can access. I suspect there is one for equality testing.

I tried using C++ code (hiding Map.find behind a C++ function) but that doesnt seem to work either.

Try adding this right below the declaration.



template<>
struct TStructOpsTypeTraits<FCombinableKey> : public TStructOpsTypeTraitsBase2<FCombinableKey>
{
    enum
    {
        WithIdenticalViaEquality = true,
    };
};


I’m not 100% certain but I think without this, it will just do memcmp to see if they are identical.

Your == operator is just outsourcing the check to UItem’s == operator (that you might not have implemented).
It’s just better to give your UItem class a FGuid Id which you can compare within operators or simply compare UItems by FName there.

UItem is just a DataAsset, which means same pointer means same item.
Also thats not the problem. the == operator is never called as stated in my second post.

the solution from TheJamsh seems to be solving my issue though.

lol that is very weird behavior, operator not called.

Doesnt seem too weird. Multiple people seem to have the same problem.