TArray Find() C2678 error even with operator overload '=='

I am trying to create an inventory based system using two USTRUCTS FAlchemyItem (FAI) and FAlchemyFluid (FAF). The FAlchemyItem contains and FAlchemyFluid and is generally used as a transporter for the FAF as multiple different FAI’s can have the same FAF.

The inventory is a TArray. There is a Find() in the processor when attempting to add the ‘item’ to the inventory.

Error Log:

Array.h(886): error C2678: binary ‘==’: no operator found which takes a left-hand operand of type ‘const FAlchemyFluid’ (or there is no acceptable conversion)

.

Array.h(886): note: while trying to match the argument list '(const FAlchemyFluid, FAlchemyFluid *const )

.

GameplayController.cpp(39): note: see reference to function template instantiation 'int32

.

TArray::IndexOfByKey(const KeyType &) const’ being compiled

with

[

KeyType=FAlchemyFluid *

]

(Appologies for the ‘.’ I’m using them to keep the error log neat.)

I have tried multiple different ways of overloading the operator and have to no avail been able to solve this. At this point I have no idea what the error even is. Could id be that the comparision is trying to compare to a nullptr?


FAlchemyFluid Definition:

USTRUCT(BlueprintType)
struct FAlchemyFluid : public FTableRowBase {

GENERATED_BODY()


public:
// Unique Fluid ID
UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FName FluidID;

bool operator==(const FAlchemyFluid &other) const {
	if (FluidID == other.FluidID) { return true; }
	else { return false; }
}
};

FluidInventory Definition:

UPROPERTY(BlueprintReadWrite, VisibleAnywhere)
TArray<FAlchemyFluid> FluidInventory;

Use of the Find():

void AGameplayController::AddItemToInventoryByID(FName ID) {

AGameplayGameMode *GameMode = Cast<AGameplayGameMode>(GetWorld()->GetAuthGameMode());
UDataTable *ItemTable = GameMode->GetItemDB();
UDataTable *FluidTable = GameMode->GetFluidDB();

const FAlchemyItem *ItemToAdd = ItemTable->FindRow<FAlchemyItem>(ID, "");
const FAlchemyFluid *FluidToAdd = FluidTable->FindRow<FAlchemyFluid>((ItemToAdd->Fluid.FluidID), "");

if (ItemToAdd) {
	if (FluidToAdd) {
		//Checks to see if fluid is in inventory already and increments it by item value
		int32 i;
		if (FluidInventory.Find(*FluidToAdd, i)) {
			FAlchemyFluid *ExistingFluid = FluidInventory.FindByKey(ItemToAdd->Fluid);
			FluidInventory[FluidInventory.IndexOfByKey(ExistingFluid)].Volume += ItemToAdd->Value;
			
		}
		else { FluidInventory.Add(*FluidToAdd); }
	}
}
}

Please let me know if I didn’t provide enough information. I will respond ASAP.
Thank you for your help

The compiler says

no operator found which takes a left-hand operand of type ‘const FAlchemyFluid’

He can’t compare the two: (const FAlchemyFluid, FAlchemyFluid *const )

Which is pretty logical, because you cannot compare a pointer and an object. I am not sure which line has caused this error, so just go to this line and try to give it a non pointer input instead.

edit:. you probably want to learn the difference of "const T*" and "T* const".

in your case, you create a pointer to const object, rather than const pointer to object.

How then would I go about fixing this as, if I understand you correctly, this FAlchemyFluid *const is being set in the Find()? Or is this being set in my operator overload?

Edit: I need to do a lot more learning. Can you direct me to some resources, please?

Also thank you so much for the help. I really appreciate it.

np :]

you shall be able to understand the difference after reading this c - Constant pointer vs Pointer to constant - Stack Overflow

also i am not sure what you mean by “being set”. find() doesn’t set anything, it’s a pure function.

In any case when you see “operator==” errors, 99% chance that you supply wrong type than expected.
mind that these are different types:

const T != T

const T* != T*

const T* != T* Const

What I meant by the set in find is that when it uses the ‘==’ operator it sets constants that I will need to match then for my operator overload. However, I can not seem to match the form.

Based on MVS the forced const for this is (const FAlchemyFluid *const this) and the other is (const FAlchemyFluid *const other) for the overload function:

bool operator==(const FAlchemyFluid *const other) const{
		if (other->FluidID == this->FluidID) { return true; }
		else { return false; }
}

yet it still throws the same error even with the const forms matching.

perhaps I shouldn’t be comparing the pointers themselves, but I’ve tried referencing ‘this’ to get the contents of ‘this’ to do the comparison and it hasn’t worked.

Edit: Obviously, I’m doing something wrong, but I have no idea what nor and idea on how to fix it. Send Help.

1 Like

you should play with variations of declaring your variable in different forms, like const/non-const/const-pointer/const-pointer-to-const etc…

one of them should work.
to help you more specifically i need to know which lines cause this behaviour. please isolate the relevant parts of the code

I think you have to dereference ExistingFluid when passing it to IndexOfByKey(). The == operator should be fine as it is.

BTW I personally prefer to write const always right of the thing it makes constant, because it`s more consistent:

T const*
T* const
T const * const
1 Like

Here is the entirety of the error log

2>E:\Program Files\Epic Games\UE_4.19\Engine\Source\Runtime\Core\Public\Containers/Array.h(941): error C2679: binary '==': no operator found which takes a right-hand operand of type 'const FName' (or there is no acceptable conversion)
2>AlphaAlphaCharacter.h(87): note: or       'bool operator ==(const FName,const FName &)' [found using argument-dependent lookup]
2>AlphaAlphaCharacter.h(91): note: or       'bool operator ==(const FAlchemyFluid,const FAlchemyFluid &)' [found using argument-dependent lookup]
2>Engine\Source\Runtime\Core\Public\Containers/Array.h(941): note: while trying to match the argument list '(FAlchemyFluid, const FName)'
2>GameplayController.cpp(38): note: see reference to function template instantiation 'FAlchemyFluid *TArray<FAlchemyFluid,FDefaultAllocator>::FindByKey<FName>(const KeyType &)' being compiled
2>        with
2>        [
2>            KeyType=FName
2>        ]
2>E:\Unreal Projects\AlphaAlpha\Source\AlphaAlpha\GameplayController.cpp(38): note: see reference to function template instantiation 'FAlchemyFluid *TArray<FAlchemyFluid,FDefaultAllocator>::FindByKey<FName>(const KeyType &)' being compiled
2>        with
2>        [
2>            KeyType=FName
2>        ]
2>UnrealBuildTool : error : UBT ERROR: Failed to produce item: E:\Unreal ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■-Win64-DebugGame.dll
2>Total build time: 13.26 seconds (Local executor: 0.00 seconds)
2>E:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\VC\VCTargets\Microsoft.MakeFile.Targets(44,5): error MSB3075: The command ""E:\Program Files\Epic Games\UE_4.19\Engine\Build\BatchFiles\Build.bat" AlphaAlphaEditor Win64 DebugGame "E:\Unreal Projects\AlphaAlpha\AlphaAlpha.uproject" -WaitMutex -FromMsBuild" exited with code 5. Please verify that you have sufficient rights to run this command.
2>Done building project "AlphaAlpha.vcxproj" -- FAILED.

It says in my example line 15 is one of the errors.

it doesn’t help in any way. to help you more specifically i need to know which lines cause this behaviour. please isolate the relevant parts of the code

After a long amount of time and thinking on this reply

you should play with variations of declaring your variable in different forms, like const/non-const/const-pointer/const-pointer-to-const etc…

one of them should work. to help you more specifically I need to know which lines cause this behavior. please isolate the relevant parts of the code

made by Arty-McLabin I came to the conclusion that I would have to not use the predefined functions. By using the for loop

for (FAlchemyFluid &fluid : FluidInventory) {
				if (FluidInventory.Num() == FluidSlots) {
					//Prevent user from picking up new fluids and notify them.
				}
				else if (fluid == *FluidToAdd) {

				}
				else { 
					FluidInventory.Add(*FluidToAdd); 
				}
			}

For some reason, the prior way I iterated through the string and the way it derived the equivalency operator statement just would not work with my code. So instead I did it on my own and I have had no issues now. The operator had no issues as j.muller RFG speculated.

Thank you both of you, with your help I was able to find a proper solution.

glad you have solved it :stuck_out_tongue:

Ok, i found whats exacly cause this error, its .Contains() function of TArray, the only solution i found its using iteration with equal conditions instead of .Contains() function, but it feels wrong.

I think I have the same issue in here: Issue

The error is not related to the function Find but to the IndexOfByKey.
IndexOfByKey expects a ref-to-const and you pass the pointer. (ExistingFluid)
Change from

FAlchemyFluid *ExistingFluid = FluidInventory.FindByKey(ItemToAdd->Fluid);
			FluidInventory[FluidInventory.IndexOfByKey(ExistingFluid)].Volume += ItemToAdd->Value;

to

FAlchemyFluid *ExistingFluid = FluidInventory.FindByKey(ItemToAdd->Fluid);
			FluidInventory[FluidInventory.IndexOfByKey(*ExistingFluid)].Volume += ItemToAdd->Value;

should fix this.

1 Like