Template Argument Type Deduction Fails with C++11 <type_traits>
typename std::enable_if<std::is_unsigned<U>::value,U>::type
is not a deducible context. In order to deduce U
from this the compiler would need the ability to apply the reverse operation of std::enable_if
. It doesn't look too hard, that's true, but that's because you are talking about a simple thing like enable_if
. It would be impossible to require this of every trait, so C++ just plays it cool and does not make any kind of weird rule exceptions: it's not deducible in general, it's not deducible in this one.
You can do it this way instead:
template<class U, class S,
EnableIf<std::is_unsigned<U>, std::is_signed<S>>...>
U add(U a, S b)
Or in compilers that don't support that style properly you can just add an extra defaulted argument:
template<class U, class S>
U add(U a, S b,
typename std::enable_if<std::is_unsigned<U>::value
&& std::is_signed<S>::value,void>::type* = nullptr)
... or mess up the return type.
template<class U, class S>
typename std::enable_if<std::is_unsigned<U>::value
&& std::is_signed<S>::value,U>::type
add(U a, S b)
You are not giving the compiler a chance to deduce U
and S
. You can rewrite your function as follows, and move the SFINAE checks in the template parameter list:
template<class U, class S,
typename std::enable_if<std::is_unsigned<U>::value &&
std::is_signed <S>::value
>::type* = nullptr>
inline U add(U a, S b)
{
return a + b;
}
Here is a live example.
You first have to deduce the types before you can reason about the types!
It should be:
template <typename U, typename S>
typename std::enable_if<std::is_unsigned<U>::value &&
std::is_signed<S>::value>, U>::type
add(U u, S s)
{
// ...
}