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 where I (the developer) know the divisor will be a power of 2, but I can’t “prove” this in code to the compiler.

`template <typename P> constexpr P log2_of_power_of_2(P non_negative_power_of_2) noexcept { static_assert(std::is_integral<P>::value, "Only integral types are supported"); static_assert(sizeof(P) <= sizeof(unsigned long long), "Unexpectedly large type"); using cast_target_type = typename std::conditional<sizeof(P) <= sizeof(unsigned), unsigned, typename std::conditional<sizeof(P) <= sizeof(unsigned long), unsigned long, unsigned long long >::type >::type; return log2_of_power_of_2<cast_target_type>( static_cast<cast_target_type>(non_negative_power_of_2)); } template <> constexpr unsigned log2_of_power_of_2<unsigned>(unsigned non_negative_power_of_2) noexcept { return __builtin_ctz (non_negative_power_of_2); } template <> constexpr unsigned long log2_of_power_of_2<unsigned long>(unsigned long non_negative_power_of_2) noexcept { return __builtin_ctzl (non_negative_power_of_2); } template <> constexpr unsigned long long log2_of_power_of_2<unsigned long long>(unsigned long long non_negative_power_of_2) noexcept { return __builtin_ctzll(non_negative_power_of_2); } template <typename I, typename P> constexpr I div_by_power_of_2(I dividend, P power_of_2_divisor) noexcept { return dividend >> 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.