Search code examples
c++templatestraitsunsigned-integer

C++ template trait to specify any unsigned integral type


I’m trying to implement a function which accepts only unsigned integral types. Below is what I’ve tried so far. It works for "unsigned int", but why doesn’t this compile for an "unsigned short?"

#include <iostream>
#include <type_traits>

template<typename T, class = typename std::enable_if<std::is_unsigned<T>::value>::type>
inline const T oddProduct(T n) noexcept {
    return (n <= 1) ? n : (n % 2) ? oddProduct(n - 2)*n : oddProduct(--n);
}

int main() {
    std::cout << "Product of odd integers from 1 to 15: " << oddProduct<unsigned short>(15) << std::endl;

    return 0;
}

Note: MSVS 2017 Community C++14 options.


Solution

  • The thing is that due to the integral promotion:

    n - 2
    

    has a type of int which is not unsigned.

    You might try to add static_cast:

    template<typename T, class = typename std::enable_if<std::is_unsigned<T>::value>::type>
    inline const T oddProduct(T n) noexcept {
        return (n <= 1) ? n : (n % 2) ? oddProduct(static_cast<T>(n - 2))*n : oddProduct(--n);
                                                   ^^^^^^^^^^^^^^
    }
    

    so n - 2 is casted to unsigned short when you call oddProduct<unsigned short>.

    Another possible option is to change 2 to 2U.


    Also note, that, once you use C++14, you might use std::enable_if_t:

    class = typename std::enable_if_t<std::is_unsigned<T>::value>
    

    DEMO