添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
还单身的弓箭  ·  TypeError: a ...·  2 小时前    · 
悲伤的茄子  ·  uni-app unipush + 个推 ...·  6 小时前    · 
帅气的松球  ·  JSON_ARRAYAGG | ...·  7 小时前    · 
谈吐大方的大白菜  ·  Use ...·  18 小时前    · 
有胆有识的键盘  ·  Smart Strings | ...·  23 小时前    · 
面冷心慈的马克杯  ·  Vue3 ...·  1 周前    · 
彷徨的马铃薯  ·  Welcome to ...·  3 月前    · 

I have a rather strange mapping in my game’s C++ that attempts to approximate the following pseudo-JSON:

/* multidimensional mapping of spell names to metamagic source id to spell aspect (borrowed fun names from the Pathfinder schools o' magic; they just serve to inform the timing and manner of lambda calling/application) to categorical metamagic effects to the actual function to run e.g. */
	   "snowball" : {
	     "ID_CracklingVioletVial" : {
	       "Conjuration" : {
	         "CreationModifier" : lambda fn that creates one or more bullet Actors and returns the resultant ASnowball array 
	       "Evocation" : {
	         "DamageModifier" : lambda fn that doubles damage,
		       "DurationModifier" : lambda fn that doubles duration
	       "Enchantment" : {
	         "EffectModifier" : lambda fn that applies an effect when the spell hits a target
	       "Transmutation" : {
	         "SpawnModifier" : lambda fn that defines how/how many/where/when etc. the spell Actor is spawned, if relevant...

The jank C++ I came up with to accomplish this is as follows:

* @brief mapping of string to inner maps that eventually terminate in a leaf node value of one of a set of unioned std::functions with various signatures as required for various effects. Phase order is Conjuration -> Evocation -> Enchantment -> Transmutation std::unordered_map<std::string /*SpellID, which is derived from the UClass::GetName() result for classes like AFireSnowball*/, std::unordered_map<std::string /*SourceID, which is derived from the UClass:GetName() result for classes like UDiademHellfireMightItem*/, std::unordered_map<std::string /*PhaseID*/, std::unordered_map<std::string /*MetamagicID*/, std::variant< /*creation function*/ std::function<std::vector<ASnowball*>/*created instances*/(ARyddelmystCharacter* /*creating character*/)>, /*spawn function*/ std::function<void(ARyddelmystCharacter* /*TransmutingCharacter*/, const FTransform& /*SpawnTransform*/, const FVector& /*LaunchDirection*/, const std::vector<ASnowball*>& /*Bullets spawned in map*/)>, /*transform function*/ std::function<void(ASnowball* /*TransformedActor*/, const FTransform& /*transform data*/)>, /*attr modifier function*/ std::function<void(ASnowball* /*bullet to modify*/)>, /*attr modifier function for FireSnowball specifically*/ //std::function<void(AFireSnowball* /*bullet to modify*/)>, // todo: why tf does this not work? With it uncommented all of sudden everyone trying to install lambdas with the ASnowball sig throw "error no viable overloaded '='..." /*damage modifier function*/ std::function<void(ASnowball* /*bullet to modify*/, float /*damage scaling factor*/, TSubclassOf<UDamageType> /*changing the damage type*/)>, /*duration modifier function*/ std::function<void(ASnowball* /*bullet to modify*/, float /*duration scaling factor*/)>, /*enchantment function*/ std::function<void(AActor* /*EnchantedActor*/, const FHitResult& /*HitResult data*/)>

and the usage looks something like:

Character->GetMetamagicMap()[std::string(TCHAR_TO_UTF8(*AIceySnowball::StaticClass()->GetName()))][std::string(TCHAR_TO_UTF8(*USlippersOfLongWintersNapItem::StaticClass()->GetName()))][ARyddelmystCharacter::ID_SPELL_PHASE_EVOCATION][ARyddelmystCharacter::ID_METAMAGIC_CATEGORY_ATTR] = [](ASnowball* Snowball)
			UE_LOG(LogTemp, Warning, TEXT("Metamagic Ice lambda; attr modifier effect"));
			// todo: how come std::variant didn't seem to want me storing a lambda sig of both ASnowball and AIceySnowball (and nothing else, such that they're identical other than the input type)?  I guess it figured since AIceySnowball is also ASnowball that it would be ambiguous... but it isn't and that's stupid
			UAttack* Attack = Cast<AIceySnowball>(Snowball)->GetSpellSphereComponent()->GetWeapon()->GetCurrentAttack();
			Cast<UIcySnowballAttack>(Attack)->SetFreezeDuration(2.f);

Against all odds and at least three laws of physics, this actually used to work as of UE 5.1. I recently upgraded to 5.2 and now all of a sudden compilation fails citing numerous issues with the MetaMagicMap unordered_map such as:

In file included from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/__functional/boyer_moore_searcher.h:25:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/unordered_map:580:17: error: type 'const std::hash<std::string>' does not provide a call operator
        {return static_cast<const _Hash&>(*this)(__x);}
                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/__hash_table:1992:21: note: in instantiation of member function 'std::__unordered_map_hasher<std::string, std::__hash_value_type<std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>>, std::hash<std::string>, std::equal_to<std::string>, true>::operator()' requested here
    size_t __hash = hash_function()(__k);
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/unordered_map:1813:21: note: in instantiation of function template specialization 'std::__hash_table<std::__hash_value_type<std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>>, std::__unordered_map_hasher<std::string, std::__hash_value_type<std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>>, std::hash<std::string>, std::equal_to<std::string>, true>, std::__unordered_map_equal<std::string, std::__hash_value_type<std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>>, std::equal_to<std::string>, std::hash<std::string>, true>, std::allocator<std::__hash_value_type<std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>>>>::__emplace_unique_key_args<std::string, const std::piecewise_construct_t &, std::tuple<std::string &&>, std::tuple<>>' requested here
    return __table_.__emplace_unique_key_args(__k,
/Users/jeffrey.creswell/gamedev/ryddelmyst/Ryddelmyst 5.2/Source/Ryddelmyst/Private/SlippersOfLongWintersNapItem.cpp:17:101: note: in instantiation of member function 'std::unordered_map<std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>>::operator[]' requested here
                Character->GetMetamagicMap()[std::string(TCHAR_TO_UTF8(*AIceySnowball::StaticClass()->GetName()))][std::string(TCHAR_TO_UTF8(*USlippersOfLongWintersNapItem::StaticClass()->GetName()))][ARyddelmystCharacter::ID_SPELL_PHASE_EVOCATION][ARyddelmystCharacter::ID_METAMAGIC_CATEGORY_ATTR] = [](ASnowball* Snowball)
In file included from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/__functional/boyer_moore_searcher.h:25:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/unordered_map:568:11: error: call to implicitly-deleted default constructor of 'std::hash<std::string>'
        : _Hash() {}
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/__memory/compressed_pair.h:64:52: note: in instantiation of member function 'std::__unordered_map_hasher<std::string, std::__hash_value_type<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>, std::hash<std::string>, std::equal_to<std::string>, true>::__unordered_map_hasher' requested here
  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __compressed_pair_elem(__default_init_tag) {}
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/unordered_map:1089:5: note: in instantiation of member function 'std::__hash_table<std::__hash_value_type<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>, std::__unordered_map_hasher<std::string, std::__hash_value_type<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>, std::hash<std::string>, std::equal_to<std::string>, true>, std::__unordered_map_equal<std::string, std::__hash_value_type<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>, std::equal_to<std::string>, std::hash<std::string>, true>, std::allocator<std::__hash_value_type<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>>>::__hash_table' requested here
    unordered_map()
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/tuple:1775:7: note: in instantiation of member function 'std::unordered_map<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>::unordered_map' requested here
      second(_VSTD::forward<_Args2>(_VSTD::get<_I2>(__second_args))...)
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/__utility/pair.h:257:11: note: in instantiation of function template specialization 'std::pair<const std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>>::pair<std::string &&, 0UL>' requested here
        : pair(__pc, __first_args, __second_args,
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/__memory/allocator.h:165:28: note: in instantiation of function template specialization 'std::pair<const std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>>::pair<std::string &&>' requested here
        ::new ((void*)__p) _Up(_VSTD::forward<_Args>(__args)...);
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/__memory/allocator_traits.h:290:13: note: in instantiation of function template specialization 'std::allocator<std::__hash_node<std::__hash_value_type<std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>>, void *>>::construct<std::pair<const std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>>, const std::piecewise_construct_t &, std::tuple<std::string &&>, std::tuple<>>' requested here
        __a.construct(__p, _VSTD::forward<_Args>(__args)...);
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/__hash_table:2382:20: note: in instantiation of function template specialization 'std::allocator_traits<std::allocator<std::__hash_node<std::__hash_value_type<std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>>, void *>>>::construct<std::pair<const std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>>, const std::piecewise_construct_t &, std::tuple<std::string &&>, std::tuple<>, void>' requested here
    __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_),
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/__hash_table:2013:29: note: in instantiation of function template specialization 'std::__hash_table<std::__hash_value_type<std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>>, std::__unordered_map_hasher<std::string, std::__hash_value_type<std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>>, std::hash<std::string>, std::equal_to<std::string>, true>, std::__unordered_map_equal<std::string, std::__hash_value_type<std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>>, std::equal_to<std::string>, std::hash<std::string>, true>, std::allocator<std::__hash_value_type<std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>>>>::__construct_node_hash<const std::piecewise_construct_t &, std::tuple<std::string &&>, std::tuple<>>' requested here
        __node_holder __h = __construct_node_hash(__hash, _VSTD::forward<_Args>(__args)...);
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/unordered_map:1813:21: note: in instantiation of function template specialization 'std::__hash_table<std::__hash_value_type<std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>>, std::__unordered_map_hasher<std::string, std::__hash_value_type<std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>>, std::hash<std::string>, std::equal_to<std::string>, true>, std::__unordered_map_equal<std::string, std::__hash_value_type<std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>>, std::equal_to<std::string>, std::hash<std::string>, true>, std::allocator<std::__hash_value_type<std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>>>>::__emplace_unique_key_args<std::string, const std::piecewise_construct_t &, std::tuple<std::string &&>, std::tuple<>>' requested here
EpicGames.Core.LogEventParser is taking a significant amount of CPU time: 25.0s/31.4s (79.4%). Processed 378 lines in last 30 seconds (0 in buffer).
    return __table_.__emplace_unique_key_args(__k,
/Users/jeffrey.creswell/gamedev/ryddelmyst/Ryddelmyst 5.2/Source/Ryddelmyst/Private/SlippersOfLongWintersNapItem.cpp:17:101: note: in instantiation of member function 'std::unordered_map<std::string, std::unordered_map<std::string, std::unordered_map<std::string, std::variant<std::function<std::vector<ASnowball *> (ARyddelmystCharacter *)>, std::function<void (ARyddelmystCharacter *, const UE::Math::TTransform<double> &, const UE::Math::TVector<double> &, const std::vector<ASnowball *> &)>, std::function<void (ASnowball *, const UE::Math::TTransform<double> &)>, std::function<void (ASnowball *)>, std::function<void (ASnowball *, float, TSubclassOf<UDamageType>)>, std::function<void (ASnowball *, float)>, std::function<void (AActor *, const FHitResult &)>>>>>::operator[]' requested here
                Character->GetMetamagicMap()[std::string(TCHAR_TO_UTF8(*AIceySnowball::StaticClass()->GetName()))][std::string(TCHAR_TO_UTF8(*USlippersOfLongWintersNapItem::StaticClass()->GetName()))][ARyddelmystCharacter::ID_SPELL_PHASE_EVOCATION][ARyddelmystCharacter::ID_METAMAGIC_CATEGORY_ATTR] = [](ASnowball* Snowball)
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/__functional/hash.h:639:36: note: default constructor of 'hash<std::string>' is implicitly deleted because base class '__enum_hash<std::string>' has a deleted default constructor
struct _LIBCPP_TEMPLATE_VIS hash : public __enum_hash<_Tp>
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/__functional/hash.h:633:5: note: '__enum_hash' has been explicitly marked deleted here
    __enum_hash() = delete;

There are numerous other complaints about using strings in unordered_map throughout the error logs, but they all pretty much fall into this pattern of the compiler seeming to have no idea how to hash strings.
As far as I can see, the root of the problem comes from Apple’s STL implementation or possibly some new rule in C++17 that requires my code to change somehow? I tried specifying the hash function to be std::hashstd::string in case it couldn’t figure that out implicitly, but that made no difference. Also made sure I had <unordered_map> and included wherever relevant. I’m not sure what else it might want from me.

I’m giving it std::string keys to deal with and that should simply cause the canned string hashing specialization to be used, right? Any thoughts on what caused this after the 5.2 upgrade and how I can fix it? I’d also welcome recommendations for a better way to achieve nested mappings like this in C++ :slight_smile:

EDIT: I tried building the same code on Windows and it works, so I guess the issue is Mac OSX specific somehow.

I tried creating a fresh C++ FPS project with UE 5.2 and putting some similar std::unordered_map shenanigans in it and it compiles just fine with the same toolchain. I must be doing something very strange somewhere in my main project that’s throwing off the compiler and likely producing a cascade of red herring nonsense errors. That or maybe something somewhere went terribly wrong with the 5.1 → 5.2 migration and I should move the code and assets manually into a fresh project?

sigh it turned out to be the thing the ol’ internet suggested in the first place for this crazed error, a missing include. In my case it was caused by creating an std::unordered_map<std::string, float> in a header file without including <string>. I guess MSVC is more tolerant than clang of such oversights?