How do you pass in a variable to a predicate?

Hi All

How would you pass a variable into a predicate? I need to use TArray ContainsByPredicate(), but one FName key (in the array) is inside a struct, the other FName comes from a character class. I’ve been using predicates for sorting structs in the arrays;

struct FCompareKey
{
	FORCEINLINE bool operator() (const FStruct& A, const FStruct& B) const
	{
		return A.Key < B.Key;
	}
}; 

Just wondering how to define a == that passes in one FName and compares it against the keys in the structs?

Thanks!

EDIT:

I’ve followed a couple of posts on Stack Overflow and done this;

struct FCompareKey
{

	FCompareKey(FName A) : A(A)
	{
	}

	FORCEINLINE bool operator() (FStruct* B) const
	{
		return A == B->Key;
	}

private:

	FName A;
};

This doesn’t work. Error C2064; term does not evaluate to a function taking one arguments.

EDIT:

Another version that doesn’t work, using Lambda;

if (!PlayerState->State.ContainsByPredicate([](FStruct* Result) {return Character->MyFName == Result->Key; })) {

Error- an enclosing local variable cannot be referenced in a lambda body unless it is in the capture list

This compiles;

FName Check = Character->MyFName;
if (!PlayerState->State.ContainsByPredicate([&](FStruct* Result) {return Check == Result->Key; })) { etc...

Yes, the [&] in the lambda body tells the compiler to capture outer variables by reference. So your Check variable within the context of the lambda is a reference to the one above. If you had use [=] instead, then the Check variable within the context of the lambda would be a copy of the one of the stack.

In the example code you have written here, it’s unlikely to make any practical difference, as the compiler will likely optimise them out to be the same thing anyway. It would make a difference if you wrote it like this:

FName Check = Character->MyFName;
auto MyPredicate = [&](FStruct* Result) {return Check == Result->Key; };
Check = AnotherCharacter->MyFName;
if (!PlayerState->State.ContainsByPredicate(MyPredicate))
{
    etc...

… because using [&] in this case means that the Check in the lambda would be a reference to the outer Check and so the call would be looking for AnotherCharacter’s name. If it was [=], it would be a copy of the name that Check had at the time the predicate was created, which would be Character’s name.

The first code you wrote with the struct should work too, assuming you called it like this:

if (!PlayerState->State.ContainsByPredicate(FCompareKey(Character->MyFName)))
{
    etc...

Steve