How does one correctly expose a function to blueprints with a TMap<anything, UInterface> in C++?

How do you correctly create a Blueprint exposed TMap with a Uinterface as the value type in C++?

Here is what I want to do in C++:
Here is the parameter I want to add in C++ but working in BP:


Here is the simple interface:

Here is my attempt at the function in C++:

	UFUNCTION(BlueprintCallable)
	void AddColumn(TMap<FName, TScriptInterface<ITUGGDebugTextable>>& Column);

Here is a working C++ version of the BP interface:

// This class does not need to be modified.
UINTERFACE(MinimalAPI, Blueprintable)
class UTUGGDebugTextable : public UInterface
{
	GENERATED_BODY()
};

/**
 * 
 */
class TUGGCORERUNTIME_API ITUGGDebugTextable
{
	GENERATED_BODY()

	// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:
	UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Errors")
	void SetText(const FText& Text);
};

Here is an example of the error I get

  [2/2] Compile Module.TUGGCoreRuntime.gen.cpp
XXX\TUGGCore\Intermediate\Build\Win64\UnrealEditor\Inc\TUGGCoreRuntime\GameplaySettingsDebugUIHelper.gen.cpp(20): error C3203: 'TScriptInterface': unspecialized class template can't be used as a template argument for template parameter 'InValueType', expected a real type
 XXX\TUGGCore\Intermediate\Build\Win64\UnrealEditor\Inc\TUGGCoreRuntime\GameplaySettingsDebugUIHelper.gen.cpp(23): error C2664: 'void UGameplaySettingsDebugUIHelper::AddColumn(TMap<FName,TScriptInterface<ITUGGDebugTextable>,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<InKeyType,InValueType,false>> &)': cannot convert argument 1 from 'TMap<FName,int32,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<InKeyType,InValueType,false>>' to 'TMap<FName,TScriptInterface<ITUGGDebugTextable>,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<InKeyType,InValueType,false>> &'
          with
          [
              InKeyType=FName,
              InValueType=TScriptInterface<ITUGGDebugTextable>
          ]
          and
          [
              InKeyType=FName,
              InValueType=int32
          ]
          and
          [
              InKeyType=FName,
              InValueType=TScriptInterface<ITUGGDebugTextable>
          ]
  XXX\TUGGCore\Source\TUGGCoreRuntime\Public\Debug\GameplaySettingsDebugUIHelper.h(21): note: see declaration of 'UGameplaySettingsDebugUIHelper::AddColumn'

Strangely, this builds just fine!

	UFUNCTION(BlueprintCallable)
	void AddColumn(TArray<TScriptInterface<ITUGGDebugTextable>>& Column);

So why is TMap different than TArray?

I have tried every solution I can think of and every solution I can find online. Before I file a suspected bug report, I am hoping a community member can enlighten me. It appears the generated CPP is invalid, yet, somehow I can do this exact thing in BP. There is an old bug here: Array of Interfaces, blueprintable c++ function parameter - #16 by UnrealEverything I suspect this is related if my code is good (which it may not be).

How do you correctly create a Blueprint exposed TMap with a Uinterface as the value type?

Potential solution. Works but I would prefer a Map of the correct type. I am going to leave this question open to see if there are better ways in case anyone else in the future makes the BP → C++ jump.

	UFUNCTION(BlueprintCallable)
	void AddColumn(const FName ColName, const TMap<FName, UObject*>& Column);

Interesting, havn’t looked too deep into UE5 yet so cannot say for sure. What you could also try to do is wrap the TScriptInterface<ITUGGDebugTextable> in a USTRUCT. That way you would get to use your interface instead of just UObject*. If it’s actually caused by bad code generation from UnrealHeaderTool the CustomThunk solution should probably also work.

1 Like

Definitely looks like a bug.
The generated code for VM-conversion omits the TScriptInterface specialization for TMap, but not for TArray :

image

UnrealHeaderTool has some hardcoded handling for TScriptInterface within TArray. It doesn’t handle them in TMap or TSet :

2 Likes

I will investigate that. Thank you for your solution.

Thank you, sir. I will submit a report that refers this answer.