I encountered a situation where the ordering of function overloads matters when using SFINAE. The cause must be the SFINAE part with the std::enable_if ((I additionally tested the code without the std::enable_if, just with templates and then the code runs, regardless the ordering of function overloads.))
I made a minimal working example out of it.
This code block works
#include <type_traits>
template <bool C, typename R = void>
using EnableIf = typename std::enable_if<C, R>::type;
template <typename T, typename R = void>
using IfIsArithmetic = EnableIf<std::is_arithmetic<T>::value, R>;
template <typename S>
IfIsArithmetic<S, void> Add(S const &scalar1, S const &scalar2, S &ret)
{
ret = scalar1 + scalar2;
}
template <typename S>
IfIsArithmetic<S, S> Add(S const &scalar1, S const &scalar2)
{
S ret;
Add(scalar1, scalar2, ret);
return ret;
}
using T = float;
int main(){
T a = 3.1;
T b = 3.5;
T c{Add(a, b)};
}
whereas the following doesn't compile (the implementations of the Add() functions are swapped)
#include <type_traits>
template <bool C, typename R = void>
using EnableIf = typename std::enable_if<C, R>::type;
template <typename T, typename R = void>
using IfIsArithmetic = EnableIf<std::is_arithmetic<T>::value, R>;
template <typename S>
IfIsArithmetic<S, S> Add(S const &scalar1, S const &scalar2)
{
S ret;
Add(scalar1, scalar2, ret);
return ret;
}
template <typename S>
IfIsArithmetic<S, void> Add(S const &scalar1, S const &scalar2, S &ret)
{
ret = scalar1 + scalar2;
}
using T = float;
int main(){
T a = 3.1;
T b = 3.5;
T c{Add(a, b)};
}
The compiler gives the following error
test.cpp: In instantiation of ‘IfIsArithmetic<S, S> Add(const S&, const S&) [with S = float; IfIsArithmetic<S, S> = float]’:
test.cpp:28:15: required from here
test.cpp:13:5: error: no matching function for call to ‘Add(const float&, const float&, float&)’
Add(scalar1, scalar2, ret);
~~~^~~~~~~~~~~~~~~~~~~~~~~
test.cpp:10:22: note: candidate: template<class S> IfIsArithmetic<S, S> Add(const S&, const S&)
IfIsArithmetic<S, S> Add(S const &scalar1, S const &scalar2)
^~~
test.cpp:10:22: note: template argument deduction/substitution failed:
test.cpp:13:5: note: candidate expects 2 arguments, 3 provided
Add(scalar1, scalar2, ret);
~~~^~~~~~~~~~~~~~~~~~~~~~~
It seems, that the compiler tries to use the first function overload, even though the signature doesn't align.
Maybe some of you can give me hint, to which C++ function lookup rule this issue is related!
Aucun commentaire:
Enregistrer un commentaire