VD_D
(VD_D)
September 24, 2020, 4:33am
1
I want to create a custom equality operator between two structures, MyData and MyDataComparator. They are as follows:
.h file:
USTRUCT(BlueprintType)
struct FMyData
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "My Data")
FString MyName;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "My Data")
int32 MyInt;
};
USTRUCT(BlueprintType)
struct FMyDataComparator
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "My Data")
FString MyNameToCompare;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "My Data")
int32 MyIntMax;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "My Data")
int32 MyIntMin;
inline bool operator==(const FMyData& MyDataReference);
};
.cpp file:
inline bool FMyDataComparator: operator==(const FMyData & MyDataReference)
{
return MyNameToCompare.Equals(MyDataReference.MyName) && MyIntMax > MyDataReference.MyInt && MyIntMin < MyDataReference.MyInt;
}
The actual .cpp file compiles, its the .cpp.obj file which complains:
Manager.cpp.obj : error LNK2019: unresolved external symbol "public: bool __cdecl FMyDataComparator::operator==(struct FMyData const &)" (...)
I’m assuming this is more an Unreal 4 thing than a C++ thing… why does the cpp.obj file have an unresolved external symbol?
1 Like
VD_D
(VD_D)
September 24, 2020, 4:51am
2
Answer (tsk):
In the header, this:
inline bool operator==(const FMyData& MyDataReference);
Needs to be replaced with this:
FORCEINLINE bool operator==(const FMyData& MyDataReference)
{
return MyNameToCompare.Equals(MyDataReference.MyName) && MyIntMax > MyDataReference.MyInt && MyIntMin < MyDataReference.MyInt;
}
and the cpp definition needs to be removed. Hope this helps someone in the future…
2 Likes
Emaer
(Emaer)
September 24, 2020, 12:50pm
3
This is due to a misunderstanding of what ‘inline’ keyword is.
cppreference.com
The original intent of the inline keyword was to serve as an indicator to the optimizer that inline substitution of a function is preferred over function call, that is, instead of executing the function call CPU instruction to transfer control to the function body, a copy of the function body is executed without generating the call. This avoids overhead created by the function call (passing the arguments and retrieving the result) but it may result in a larger executable as the code for the function has to be repeated multiple times.
Since this meaning of the keyword inline is non-binding, compilers are free to use inline substitution for any function that’s not marked inline, and are free to generate function calls to any function marked inline . Those optimization choices do not change the rules regarding multiple definitions and shared statics listed above. [TABLE]
**Because the meaning of the keyword inline for functions came to mean "multiple definitions are permitted" rather than "inlining is preferred", that meaning was extended to variables.**
Conclusion: trust the compiler.
This doesn’t work at all unfortunately. Certainly not in a blueprint context.
Altrue
(Altrue)
November 9, 2023, 10:01am
5
This is a C++ operator, and as you can see by the lack of macros around it, it is now know to the reflection system. There’s nothing surprising here. Custom operators obviously do work very well in a C++ context.
If you need to use them in a BP context, I would suggest exposing a UFUNCTION which c++'s code uses your equality operator. Since I don’t believe UFUNCTIONs are supported in structs, I would suggest declaring a C++ comparison function in a UBlueprintFunctionLibrary.