TMap value type limitations

Could someone clarify what types of objects can and can’t be stored in a TMap?
For example, I created:

TMap<FName, std::function<TSharedPtr<FWhatever>()>> FunctionMap;

And then stored some lambda functions in there, four in fact, everything was working fine, then I added another function into the map and the values of the first four elements got scrambled (the key values were preserved). I’m guessing the map failed to copy the std::function objects correctly while expanding its internal storage.

For now I’ve gone back to using Unreal’s delegates instead of std::function.

1 Like

Hi,

The Unreal containers are value-based, but rely on a concept that we call ‘trivial relocatability’… that is, the ability to move an object to a new memory location via memcpy. That’s not to say that objects need a trivial copy constructor, but rather that the process of ‘move-constructing an object in the new location followed by destroying the original object’ must be equivalent to a memcpy.

This is the case for almost all types, but will not work for types where the ‘this’ pointer is assumed to remain unchanged throughout the lifetime of the object. Notable examples of this are types which contain pointers to its own members, or which give out its ‘this’ pointer as a form of registration mechanism.

I believe std::function is guilty of the former (contains pointers to itself), as it contains a ‘small wrapper’ buffer to avoid heap allocations if your bound object is small enough.

You could use the Unreal delegates, or you could use TUniquePtr<std::function<…>>, which is UE’s equivalent of std::unique_ptr, which is guaranteed to be trivially relocatable. std::unique_ptr probably is likely to be too, but isn’t necessarily guaranteed.

Steve

2 Likes

Thanks for the explanation :slight_smile:

I want to upvote this reply just because we ran into the exact same issue this month, storing lambdas in a TMap.