|
#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); } |
|
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.