How to build A TMap with FString and TFunction?

Hi, I’m constantly having errors when I’m trying to build a TMap with FString as key and TFunction as values. Here are my codes:

Something.h

TMap<FString, TFunction<void(USomeActorComponent::*)()>> StringFunctionMap;

Something.cpp

USomeActorComponent::USomeActorComponent()
{
	PrimaryComponentTick.bCanEverTick = false;

	SetIsReplicated(true);
	StringFunctionMap.Add(TEXT("FunctionA"), &USomeActorComponent::BlahBlah);
}

My errors

CompilerResultsLog: Error: D:\Epic Games\Engine\Source\Runtime\Core\Public\Templates/Function.h(527) : error C2504: 'UE4Function_Private::TFunctionRefBase<TFunction<void (__cdecl USandboxComponent::* )(void)>,FuncType>': base class undefined
CompilerResultsLog:         with
CompilerResultsLog:         [
CompilerResultsLog:             FuncType=void (__cdecl USomeActorComponent::* )(void)
CompilerResultsLog:         ]
CompilerResultsLog: Error: D:\Epic Games\Engine\Source\Runtime\Core\Public\Templates/UnrealTypeTraits.h(291) : note: see reference to class template instantiation 'TFunction<void (__cdecl USomeActorComponent::* )(void)>' being compiled
CompilerResultsLog: Error: D:\Epic Games\Engine\Source\Runtime\Core\Public\Templates/UnrealTypeTraits.h(304) : note: see reference to class template instantiation 'TCallTraitsBase<T>' being compiled
CompilerResultsLog:         with
CompilerResultsLog:         [
CompilerResultsLog:             T=TFunction<void (__cdecl USomeActorComponent::* )(void)>
CompilerResultsLog:         ]
CompilerResultsLog: Error: D:\Epic Games\Engine\Source\Runtime\Core\Public\Templates/UnrealTypeTraits.h(357) : note: see reference to class template instantiation 'TCallTraits<T>' being compiled
CompilerResultsLog:         with
CompilerResultsLog:         [
CompilerResultsLog:             T=TFunction<void (__cdecl USomeActorComponent::* )(void)>
CompilerResultsLog:         ]
CompilerResultsLog: Error: D:\Epic Games\Engine\Source\Runtime\Core\Public\Templates/UnrealTypeTraits.h(368) : note: see reference to class template instantiation 'TTypeTraitsBase<T>' being compiled
CompilerResultsLog:         with
CompilerResultsLog:         [
CompilerResultsLog:             T=TFunction<void (__cdecl USandboxComponent::* )(void)>
CompilerResultsLog:         ]
CompilerResultsLog: Error: D:\Epic Games\Engine\Source\Runtime\Core\Public\Containers/Map.h(114) : note: see reference to class template instantiation 'TTypeTraits<ValueType>' being compiled
CompilerResultsLog:         with
CompilerResultsLog:         [
CompilerResultsLog:             ValueType=TFunction<void (__cdecl USandboxComponent::* )(void)>
CompilerResultsLog:         ]
CompilerResultsLog: Error: D:\Epic Games\Engine\Source\Runtime\Core\Public\Containers/Map.h(752) : note: see reference to class template instantiation 'TMapBase<KeyType,ValueType,SetAllocator,KeyFuncs>' being compiled
CompilerResultsLog:         with
CompilerResultsLog:         [
CompilerResultsLog:             KeyType=FString,
CompilerResultsLog:             ValueType=TFunction<void (__cdecl USomeActorComponent::* )(void)>,
CompilerResultsLog:             SetAllocator=FDefaultSetAllocator,
CompilerResultsLog:             KeyFuncs=TDefaultMapHashableKeyFuncs<FString,TFunction<void (__cdecl USomeActorComponent::* )(void)>,false>
CompilerResultsLog:         ]
CompilerResultsLog: Error: D:\Epic Games\Engine\Source\Runtime\Core\Public\Containers/Map.h(859) : note: see reference to class template instantiation 'TSortableMapBase<KeyType,ValueType,SetAllocator,KeyFuncs>' being compiled
CompilerResultsLog:         with
CompilerResultsLog:         [
CompilerResultsLog:             KeyType=FString,
CompilerResultsLog:             ValueType=TFunction<void (__cdecl USomeActorComponent::* )(void)>,
CompilerResultsLog:             SetAllocator=FDefaultSetAllocator,
CompilerResultsLog:             KeyFuncs=TDefaultMapHashableKeyFuncs<FString,TFunction<void (__cdecl USomeActorComponent::* )(void)>,false>
CompilerResultsLog:         ]
CompilerResultsLog: Error: D:\SVN\Source\ProjectCombine\Public\Components\USomeActorComponent.h(37) : note: see reference to class template instantiation 'TMap<FString,TFunction<void (__cdecl USomeActorComponent::* )(void)>,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<KeyType,ValueType,false>>' being compiled
CompilerResultsLog:         with
CompilerResultsLog:         [
CompilerResultsLog:             KeyType=FString,
CompilerResultsLog:             ValueType=TFunction<void (__cdecl USomeActorComponent::* )(void)>
CompilerResultsLog:         ]
CompilerResultsLog: Error: D:\Epic Games\Engine\Source\Runtime\Core\Public\Templates/Function.h(527) : error C2504: 'UE4Function_Private::TFunctionRefBase<TFunction<void (__cdecl USomeActorComponent::* )(void)>,FuncType>': base class undefined
CompilerResultsLog:         with
CompilerResultsLog:         [
CompilerResultsLog:             FuncType=void (__cdecl USomeActorComponent::* )(void)
CompilerResultsLog:         ]
CompilerResultsLog: Error: D:\Epic Games\Engine\Source\Runtime\Core\Public\Templates/UnrealTypeTraits.h(291) : note: see reference to class template instantiation 'TFunction<void (__cdecl USomeActorComponent::* )(void)>' being compiled
CompilerResultsLog: Error: D:\Epic Games\Engine\Source\Runtime\Core\Public\Templates/UnrealTypeTraits.h(304) : note: see reference to class template instantiation 'TCallTraitsBase<T>' being compiled
CompilerResultsLog:         with
CompilerResultsLog:         [
CompilerResultsLog:             T=TFunction<void (__cdecl USomeActorComponent::* )(void)>
CompilerResultsLog:         ]
CompilerResultsLog: Error: D:\Epic Games\Engine\Source\Runtime\Core\Public\Templates/UnrealTypeTraits.h(357) : note: see reference to class template instantiation 'TCallTraits<T>' being compiled
CompilerResultsLog:         with
CompilerResultsLog:         [
CompilerResultsLog:             T=TFunction<void (__cdecl USomeActorComponent::* )(void)>
CompilerResultsLog:         ]
CompilerResultsLog: Error: D:\Epic Games\Engine\Source\Runtime\Core\Public\Templates/UnrealTypeTraits.h(368) : note: see reference to class template instantiation 'TTypeTraitsBase<T>' being compiled
CompilerResultsLog:         with
CompilerResultsLog:         [
CompilerResultsLog:             T=TFunction<void (__cdecl USomeActorComponent::* )(void)>
CompilerResultsLog:         ]
CompilerResultsLog: Error: D:\Epic Games\Engine\Source\Runtime\Core\Public\Containers/Map.h(114) : note: see reference to class template instantiation 'TTypeTraits<ValueType>' being compiled
CompilerResultsLog:         with
CompilerResultsLog:         [
CompilerResultsLog:             ValueType=TFunction<void (__cdecl USomeActorComponent::* )(void)>
CompilerResultsLog:         ]
CompilerResultsLog: Error: D:\Epic Games\Engine\Source\Runtime\Core\Public\Containers/Map.h(752) : note: see reference to class template instantiation 'TMapBase<KeyType,ValueType,SetAllocator,KeyFuncs>' being compiled
CompilerResultsLog:         with
CompilerResultsLog:         [
CompilerResultsLog:             KeyType=FString,
CompilerResultsLog:             ValueType=TFunction<void (__cdecl USomeActorComponent::* )(void)>,
CompilerResultsLog:             SetAllocator=FDefaultSetAllocator,
CompilerResultsLog:             KeyFuncs=TDefaultMapHashableKeyFuncs<FString,TFunction<void (__cdecl USomeActorComponent::* )(void)>,false>
CompilerResultsLog:         ]
CompilerResultsLog: Error: D:\Epic Games\Engine\Source\Runtime\Core\Public\Containers/Map.h(859) : note: see reference to class template instantiation 'TSortableMapBase<KeyType,ValueType,SetAllocator,KeyFuncs>' being compiled
CompilerResultsLog:         with
CompilerResultsLog:         [
CompilerResultsLog:             KeyType=FString,
CompilerResultsLog:             ValueType=TFunction<void (__cdecl USomeActorComponent::* )(void)>,
CompilerResultsLog:             SetAllocator=FDefaultSetAllocator,
CompilerResultsLog:             KeyFuncs=TDefaultMapHashableKeyFuncs<FString,TFunction<void (__cdecl USomeActorComponent::* )(void)>,false>
CompilerResultsLog:         ]
CompilerResultsLog: Error: D:\SVN\Source\ProjectCombine\Public/Components/USomeActorComponent.h(37) : note: see reference to class template instantiation 'TMap<FString,TFunction<void (__cdecl USomeActorComponent::* )(void)>,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<KeyType,ValueType,false>>' being compiled
CompilerResultsLog:         with
CompilerResultsLog:         [
CompilerResultsLog:             KeyType=FString,
CompilerResultsLog:             ValueType=TFunction<void (__cdecl USomeActorComponent::* )(void)>
CompilerResultsLog:         ]
CompilerResultsLog: ERROR: UBT ERROR: Failed to produce item: D:\SVN\Binaries\Win64\UE4Editor-ProjectCombine-3410.dll
CompilerResultsLog: Total build time: 32.55 seconds (Local executor: 0.00 seconds)

Any help will be appreciated, thanks.

Are you defining the Map as a member of your USomeActorComponent class?

Yes I am, I wanted to create a map to that take a string as a key to call function because my colleague say if I use switch (which I’m using now) the function become very big. I’m thinking if I can do like
(void*()map[“key”])()
it would be nice.

I cannot say right now what is wrong with the code, but my guess is that the compiler does not have the definition for the function type you want to store or TFunction might not be compatible with containers, but I am not sure, I have to dig a little bit more.

Be aware however that defining a TFunction requires the exact function signature, so all functions stored will have to match the signature. You can not have a method that takes and int for example in your code.

My best advice right now is for you to take a look into delegates: Delegates | Unreal Engine Documentation

“Delegates allow you to call member functions on C++ objects in a generic, yet type-safe way”.
Be also aware that any technique like this is probably slower than calling the functions in a switch as you said.

All the function I’m storing are virtual void() so, it should have any issue? Or does virtual keyword matters?

This is only me trying to get a full picture of what you are trying to do. Are you going to override these functions in child classes?

The virtual void function have their own respective body in the cpp file, I’m making them as virtual void in case I have to override them in the future.

So, I was experimenting a little bit with this idea and I came up with a solution that does what you expect.

When defining your map, do it like this:

TMap<FString, TFunction<void(USomeActorComponent*)>> StringFunctionMap;

In this way you are storing a pointer to a function whose first argument is a pointer to USomeActorComponent. You just need to remember that a member function is just a function where the first parameter is the this you can use inside the function.

You can create the map in the same way:

StringFunctionMap.Add(TEXT("FunctionA"), &USomeActorComponent::BlahBlah);

The only difference will be when you call this function:

StringFunctionMap["FunctionA"](this);

You just need to remember to pass the this.

Thank you very much man, you’re are a life saver. The TFunction made me dizzy haha.

Be aware that I have not tested this for an overridden function.