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 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.