Comment undefined sont __builtin_ctz(0) ou __builtin_clozapine(0)?

Fond

Pendant une longue période, gcc a été la fourniture de un certain nombre de builtin peu-se tourner les fonctions, en particulier le nombre de fuite et de 0 bits (également pour long unsigned et long long unsigned, qui ont des suffixes l et ll):

Intégré— Fonction: int __builtin_clz (unsigned int x)

Renvoie la
nombre de 0 bits dans x, en commençant par le bit de poids fort
position. Si x est 0, le résultat est indéfini.

Intégré— Fonction: int __builtin_ctz (unsigned int x)

Renvoie la
nombre de de fuite 0-bits dans x, en commençant par le bit le moins significatif
position. Si x est 0, le résultat est indéfini.

Sur chaque ligne (avertissement: seuls x64) compilateur que j'ai testé, cependant, le résultat a été que les deux clz(0) et ctz(0) retourne le nombre de bits de la sous-jacentes builtin type, comme par exemple

#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);    
}

Live Exemple.

Tentative de contournement

La dernière Clang SVN trunk dans std=c++1y mode a fait toutes ces fonctions détendu C++14 constexpr, ce qui fait d'eux des candidats à utiliser dans un SFINAE l'expression d'une fonction wrapper modèle autour de 3 ctz /clz les builtins pour unsigned, unsigned long, et 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; }

Le gain de ce hack est que les plates-formes qui donnent le résultat requis pour ctz(0) pouvez omettre un supplément de conditionnel pour tester x==0 (qui pourrait sembler un micro-optimisation, mais lorsque vous êtes déjà au niveau du groupe builtin peu-se tourner les fonctions, il peut faire une grande différence)

Questions

Comment undefined est la famille de fonctions internes clz(0) et ctz(0)?

  • peuvent-ils jeter un std::invalid_argument exception?
  • pour x64, seront-ils de l'actuel gcc distribution de retour de la taille de la underyling type?
  • sont les ARM/x86 plates-formes différentes (je n'ai pas accès à tester ceux-ci)?
  • est au-dessus de la SFINAE truc bien définie de façon à séparer ces plates-formes?
  • Si vous pouvez obtenir vos mains sur le fichier longlong.h dans gcc/gmp/glibc, regardez pour la macro COUNT_LEADING_ZEROS_0...
InformationsquelleAutor TemplateRex | 2013-10-22