Templated division by a power of 2 I've implemented a div_by_power_of_2() function, which lets me force the compiler to use left-shifting rather than proper division, in cases when the developer know the divisor will be a power of 2, but does not know which power of 2; and the compiler cannot prove to itself that this is the case.

template &lt;typename P&gt; constexpr P log2_of_power_of_2(P non_negative_power_of_2) noexcept
{
    static_assert(std::is_integral&lt;P&gt;::value, "Only integral types are supported");
    static_assert(sizeof(P) &lt;= sizeof(unsigned long long), "Unexpectedly large type");
    using cast_target_type = typename
        std::conditional&lt;sizeof(P) &lt;= sizeof(unsigned),
            unsigned,
            typename std::conditional&lt;sizeof(P) &lt;= sizeof(unsigned long),
                unsigned long, 
                unsigned long long
            &gt;::type
        &gt;::type;
    return log2_of_power_of_2&lt;cast_target_type&gt;(
        static_cast&lt;cast_target_type&gt;(non_negative_power_of_2));
}
template &lt;&gt; 
constexpr unsigned 
log2_of_power_of_2&lt;unsigned&gt;(unsigned non_negative_power_of_2) noexcept 
{ return __builtin_ctz  (non_negative_power_of_2); }

template &lt;&gt; 
constexpr unsigned long 
log2_of_power_of_2&lt;unsigned long&gt;(unsigned long non_negative_power_of_2)  noexcept
{ return __builtin_ctzl (non_negative_power_of_2); }

template &lt;&gt;
constexpr unsigned long long 
log2_of_power_of_2&lt;unsigned long long&gt;(unsigned long long non_negative_power_of_2) noexcept 
{ return __builtin_ctzll(non_negative_power_of_2); }

template &lt;typename I, typename P&gt;
constexpr I div_by_power_of_2(I dividend, P power_of_2_divisor) noexcept
{ return dividend &gt;&gt; log2_of_power_of_2(power_of_2_divisor); }


Questions:


Is my approach to covering the possible types of power_of_2 appropriate? Can it perhaps be made less verbose but with the same effect?
Am I reinventing the wheel with this code?
Currently, this depends on certain compiler intrinsics available in GCC and clang but not necessarily elsewhere. I could generalize it a bit using this method to also support MSVC. Is there a better approach to generalizing the code?
Should I change the return type of log2_of_power_of_2 functions to be uniform rather than I? e.g. an unsigned?
Any other comments/suggestions are welcome.


Notes:


This is intended to be C++11; obviously with C++17 I could simplify it further
The constexpr qualifier is not very meaningful, since in a constexpr context we could just do plain division, but I've tacked it on nonetheless. To make the use of these utility function(s) more uniform.
The code is missing #include &lt;type_traits&gt;; it would have been nice to have had the test cases too.
It would be nice to be able to check the argument restriction using assert.  Unfortunately, this doesn't fit nicely with C++11 constexpr functions, which may contain only a single return statement.  If you might also compile against a newer standard, we could perhaps conditionally test it:
#include &lt;cassert&gt;

template &lt;typename I, typename P&gt;
constexpr I div_by_power_of_2(I dividend, P power_of_2_divisor) noexcept
{
#if __cplusplus &gt;= 201402L
    assert((power_of_2_divisor &amp; power_of_2_divisor - 1) == 0);
#endif
    return dividend &gt;&gt; log2_of_power_of_2(power_of_2_divisor);
}

I don't see why we have a template and specializations, rather than simple overloading of log2_of_power_of_2, particularly as we don't widen signed types to preserve sign.
Contrary to your comment, the constexpr is valuable, as it allows this function to be called from within another constexpr function, whether or not that one is being called with constant arguments.

Modified code
static constexpr unsigned
log2_of_power_of_2(unsigned non_negative_power_of_2) noexcept
{ return __builtin_ctz  (non_negative_power_of_2); }

static constexpr unsigned long
log2_of_power_of_2(unsigned long non_negative_power_of_2)  noexcept
{ return __builtin_ctzl (non_negative_power_of_2); }

static constexpr unsigned long long
log2_of_power_of_2(unsigned long long non_negative_power_of_2) noexcept
{ return __builtin_ctzll(non_negative_power_of_2); }

static constexpr int
log2_of_power_of_2(int non_negative_power_of_2) noexcept
{ return __builtin_ctz  (non_negative_power_of_2); }

static constexpr long
log2_of_power_of_2(long non_negative_power_of_2)  noexcept
{ return __builtin_ctzl (non_negative_power_of_2); }

static constexpr long long
log2_of_power_of_2(long long non_negative_power_of_2) noexcept
{ return __builtin_ctzll(non_negative_power_of_2); }


#include &lt;cassert&gt;

template &lt;typename I, typename P&gt;
constexpr I div_by_power_of_2(I dividend, P power_of_2_divisor) noexcept
{
#if __cplusplus &gt;= 201402L
    assert((power_of_2_divisor &amp; power_of_2_divisor - 1) == 0);
#endif
    return dividend &gt;&gt; log2_of_power_of_2(power_of_2_divisor);
}


#include &lt;iostream&gt;
int main()
{
    std::cout &lt;&lt; div_by_power_of_2(15ul, 4) &lt;&lt; '\n';
}