Open 3D Engine AzCore API Reference 23.10.0
O3DE is an open-source, fully-featured, high-fidelity, modular 3D engine for building games and simulations, available to every industry.
Multiple STL implementation helper macros - ADL issues

Macros

#define AZSTD_ADL_FIX_FUNCTION_SPEC_1(_Function, _Param)    AZ_FORCE_INLINE void _Function(_Param a) { AZStd::_Function(a); }
 
#define AZSTD_ADL_FIX_FUNCTION_SPEC_1_RET(_Function, _Return, _Param)    AZ_FORCE_INLINE _Return _Function(_Param a) { return AZStd::_Function(a); }
 
#define AZSTD_ADL_FIX_FUNCTION_SPEC_1_2(_Function, _Param)    AZ_FORCE_INLINE void _Function(_Param a, _Param b) { AZStd::_Function(a, b); }
 
#define AZSTD_ADL_FIX_FUNCTION_SPEC_1_2_RET(_Function, _Return, _Param)    AZ_FORCE_INLINE _Return _Function(_Param a, _Param b) { return AZStd::_Function(a, b); }
 
#define AZSTD_ADL_FIX_FUNCTION_SPEC_2(_Function, _Param1, _Param2)    AZ_FORCE_INLINE void _Function(_Param1 a, _Param2 b) { AZStd::_Function(a, b); }
 
#define AZSTD_ADL_FIX_FUNCTION_SPEC_2_RET(_Function, _Return, _Param1, _Param2)    AZ_FORCE_INLINE _Return _Function(_Param1 a, _Param2 b) { return AZStd::_Function(a, b); }
 
#define AZSTD_ADL_FIX_FUNCTION_SPEC_2_3(_Function, _Param1, _Param2)    AZ_FORCE_INLINE void _Function(_Param1 a, _Param1 b, _Param2 c) { AZStd::_Function(a, b, c); }
 
#define AZSTD_ADL_FIX_FUNCTION_SPEC_2_3_RET(_Function, _Return, _Param1, _Param2)    AZ_FORCE_INLINE _Return _Function(_Param1 a, _Param1 b, _Param2 c) { return AZStd::_Function(a, b, c); }
 
#define AZSTD_ADL_FIX_FUNCTION_SPEC_2_4(_Function, _Param1, _Param2)    AZ_FORCE_INLINE void _Function(_Param1 a, _Param1 b, _Param1 c, _Param2 d) { AZStd::_Function(a, b, c, d); }
 
#define AZSTD_ADL_FIX_FUNCTION_SPEC_2_4_RET(_Function, _Return, _Param1, _Param2)    AZ_FORCE_INLINE _Return _Function(_Param1 a, _Param1 b, _Param1 c, _Param2 d) { return AZStd::_Function(a, b, c, d); }
 

Detailed Description

These helper macros can be used to specialize a function for a specific type, to fix ADL issues. For example in the standard the iter_swap function takes template arguments. If we use another STL implementation and we call one of its functions which is not ADL safe there will be ambiguity.

AZStd { template<typename A, typename B> void iter_swap(A& a, B& b) {...} }
OtherStl { template<typename A, typename B> void iter_swap(A& a, B& b) {...} }
AZ namespace needs to be closed in order to specialize the AZStd::hash struct for AddressTypeElement ...
Definition: AssetCommon.h:1254

Then we have a iterator from AZStd, let's say AZStd::vector<int>::iterator and we call a sort function from OtherStl...

OtherStl::sort(azstdVectorInt.begin(),azstdVectorInt.end(),std::less<int>);

Now this code is all fine and will work fine, but if OtherStl::sort looks like

namespace OtherStl
{
template<Iterator>
sort(Iterator first, Iterator last, ...) {
...
iter_swap(first,last); <- this is a problem for ADL, it can match AZStd::iter_swap or OtherStl::iter_swap. For this code to be safe we should have OtherStl::iter_swap(first,last),
but this usually is third party code, so we can't fix it. That is why we need to specialize for the current iterators (function).
...
}
}

To fix that problem we can use the following macros which will specialize the particular type (AZStd::vector<int>::iterator from the example) to use the AZStd::iter_swap. So what we need to do is:

AZSTD_ADL_FIX_FUNCTION_SPEC_1_2(iter_swap,AZStd::vector<int>::iterator&);

This line will resolve the issue. For instance, this is a typical issue when you use AZStd with STLport.