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)
{
    // ...
}