J'ai des fonctions pour convertir différents types arithmétiques à un type de point flottant à moitié précision (juste un Ceux-ci sont appelés interne à partir d'un constructeur modélisé universel par instanciation explicite: P> uint16_t code> au niveau le plus bas) et j'ai des fonctions différentes pour les types de sources de points entier et flottant, en utilisant SFUNE et
std :: Enable_if Code>:
template<typename T>
uint16_t to_half(typename std::enable_if<std::is_integral<T>::value &&
std::is_signed<T>::value,T>::type value)
{
//signed to half conversion
}
template<typename T>
uint16_t to_half(typename std::enable_if<std::is_integral<T>::value &&
std::is_unsigned<T>::value,T>::type value)
{
//unsigned to half conversion
}
3 Réponses :
Si cela ne fonctionne pas, votre compilateur est erroné. p>
Deux expressions impliquant des paramètres de modèle sont considérés comme équivalents si deux définitions de fonction contenant les expressions satisferaient la règle d'une définition ... p> blockQuote>
C'est la règle la plus importante à considérer ici (laissé sur les détails de "..."). Vos deux modèles ne satisfont pas l'ODR parce que leurs séquences de jeton diffèrent. p>
Deux modèles de fonctions sont équivalents si elles sont déclarées dans la même portée, ont le même nom, avoir le même nom, avoir des listes de paramètres de modèle identiques et des types de retour et des listes de paramètres équivalents à l'aide des règles décrites ci-dessus pour comparer des expressions de modèle impliquant des paramètres de modèle. p> blockQuote>
Donc, vos deux modèles définissent différents modèles et ne vous heurtent pas. Vous pouvez maintenant vérifier si vos modèles sont peut-être «équivalents fonctionnellement». Ils seraient si pour tout ensemble possible d'arguments de modèle, votre expression
activer_if code> donnerait toujours la même valeur. Mais puisque ce n'est pas vrai pour
is_unsigned code> et
is_signed code>, ce n'est pas le cas non plus. Si tel serait le cas, votre code serait mal formé, mais sans nécessiter de diagnostic (ce qui signifie efficacement «comportement non défini»). P>
Remplacer is_unsigned code> avec
! IS_SIGNED code> (ou inversement) a fonctionné, alors je suppose (bien qu'elles ne soient pas bien versées dans les profondeurs de la spécification de langue, ne pas parler de modèles) qu'il y a un type qui est à la fois signé et américain. Ou peut-il être parce que les versions par défaut de ces modèles évaluent à la fois
faux code> pour les types non arithmétiques? Mais là encore, il y a aussi le
is_integral code> pour désambiguez les choses (pour des types intégrés, SHOUDL sera mutuellement exclusif, ne devrait-il pas?).
@Christian je n'ai aucune idée de ce qu'ils font, mais c'est vraiment un comportement erroné. Essayez !! is_unsigned code> au lieu de
! Is_signed code>. Je ne serais pas surpris de le voir "travailler" aussi :)
Hah, ça a fonctionné aussi. Ok maintenant je pense que ça devient vraiment un peu ridicule. Vous avez probablement raison de dire que le compilateur est en faute ici.
"Deux expressions impliquant des paramètres de modèle sont considérées comme équivalentes si deux Les définitions de fonction contenant les expressions b> satisfont à la règle d'une définition ..." Pourriez-vous expliquer cela plus loin en ajoutant un exemple dans votre message?
Votre réponse n'est que la moitié correcte. Le compilateur a été correct de rejeter le code (voir ma réponse ci-dessous), mais cela a donné la mauvaise raison.
@walter il passe explicitement l'argument
En effet il fait. Étrange. Quel est le point de Sfinae si vous faites cela?
Personnellement, j'éviterais Sfinae ici autant que possible puisque vous pouvez accomplir la même chose avec la surcharge:
+1 belle alternative. Mais comme note latérale, je pense que le dernier argument à la version flottante doit être de std :: true_type code>, car des flotteurs sont toujours signés (au moins les implémentations habituelles, pour le code de conversion non-IEEE gagné ' t fonctionne de toute façon).
@Christian: Vous êtes totalement correct; Je basais la logique des documents MSDN pour IS_SIGNED CODE>, qui se passe mal (surprise, surprise). Fixé.
L'idiome le plus courant est d'utiliser Sfinae sur le type de retour fort> plutôt que le type d'argument. sinon fort>, le type de modèle type est déductible (même de manière triviale), mais pour votre code d'origine ce n'est pas! En effet, lors de l'exécution de cette déclaration avec votre bien sûr, si on fournit explicitement l'argument de modèle (comme vous a fait), ce problème n'apparaît pas. Donc, votre code n'était pas faux (mais le compilateur), mais quel est le point de Sfinae si vous passez le type d'argument de modèle? P> p> t code> peut ne pas être déductible fort>. Avec
t code> dans l'instruction suivante p>
to_half () code> La mise en œuvre via clang donne p>
Cela ne devrait-il pas avoir les mêmes problèmes d'ambiguïté que la Sfinae dans le type d'argument? Y a-t-il une règle qui rend ce travail mais la version de l'argument non? Sinon, il ne semble pas tellement adresser la question.
Il y a une très bonne raison B> pour ne pas utiliser Sfinae sur le type d'argument, voir la réponse modifiée.
Il n'est pas clair que
is_signed code> /
is_unsigned code> est mutuellement exclusif (bonjour
char code>?). Essayez de faire la deuxième version dire
! Std :: is_signed :: valeur code> à la place.
Pouvez-vous essayer d'utiliser
std :: is_signed :: valeur code> pour l'un des membres et
! Std :: is_signed :: valeur code> pour l'autre? Ceci est juste pour vous assurer qu'il n'y a pas que certains types de paramètres incompatibles pour
is_signed code> et
is_unsigned code>.
@Kerreksb & Dietmar Hah, ça l'a fait! Je ne peux pas croire que c'était aussi facile. Si quelqu'un l'ajoute comme une réponse, je l'accepterai.
@Kerrek
Char code> n'est ni un type d'entier signé ni un type d'entier non signé. Mais IIRC
is_signed code> et
is_unsigned code> prend en charge que: un seul d'entre eux signalera
true code> pour
char code>.
@ Johannesschab-litb: vous avez raison,
char code> est ok. Les énigmes et les pointeurs sont toujours faux, cependant; Je suppose que parce qu'ils ne sont pas des types arithmétiques.