Background
For a long time, gcc has been providing a number of builtin bit-twiddling functions, in particular the number of trailing and leading 0-bits (also for long unsigned and long long unsigned, which have suffixes l and ll):
— Built-in Function:
int __builtin_clz (unsigned int x)Returns the number of leading 0-bits in
x, starting at the most significant bit position. Ifxis 0, the result is undefined.— Built-in Function:
int __builtin_ctz (unsigned int x)Returns the number of trailing 0-bits in
x, starting at the least significant bit position. Ifxis 0, the result is undefined.
On every online (disclaimer: only x64) compiler I tested, however, the result has been that both clz(0) and ctz(0) return the number of bits of the underlying builtin type, e.g.
#include <iostream>
#include <limits>
int main()
{
    // prints 32 32 32 on most systems
    std::cout << std::numeric_limits<unsigned>::digits << " " << __builtin_ctz(0) << " " << __builtin_clz(0);    
}
Attempted workaround
The latest Clang SVN trunk in std=c++1y mode has made all these functions relaxed C++14 constexpr, which makes them candidates to use in a SFINAE expression for a wrapper function template around the 3 ctz / clz builtins for unsigned, unsigned long, and unsigned long long
template<class T> // wrapper class specialized for u, ul, ull (not shown)
constexpr int ctznz(T x) { return wrapper_class_around_builtin_ctz<T>()(x); }
// overload for platforms where ctznz returns size of underlying type
template<class T>
constexpr auto ctz(T x) 
-> typename std::enable_if<ctznz(0) == std::numeric_limits<T>::digits, int>::type
{ return ctznz(x); }
// overload for platforms where ctznz does something else
template<class T>
constexpr auto ctz(T x) 
-> typename std::enable_if<ctznz(0) != std::numeric_limits<T>::digits, int>::type
{ return x ? ctznz(x) : std::numeric_limits<T>::digits; }
The gain from this hack is that platforms that give the required result for ctz(0) can omit an extra conditional to test for x==0 (which might seem a micro-optimization, but when you are already down to the level of builtin bit-twiddling functions, it can make a big difference)
Questions
How undefined is the family of builtin functions clz(0) and ctz(0)?
- can they throw an std::invalid_argumentexception?
- for x64, will they for the current gcc distro return the size of the underyling type?
- are the ARM/x86 platforms any different (I have no access to that to test those)?
- is the above SFINAE trick a well-defined way to separate such platforms?
 
     
     
    