Std :: is_unsigned :: value est-il bien défini?

Je me demande si

std::is_unsigned::value 

est bien défini selon la norme ou non?

Je pose la question car le nom de typename std::make_unsigned::type n’est pas bien défini.

Il n’y a pas de concept de dédicace pour bool . De [basic.fundamental] / 6:

Les valeurs de type bool sont soit true soit false . [ Note : Il n’y a pas de types ou de valeurs signed , unsigned , short ou long . – note finale ] Les valeurs de type bool participent aux promotions intégrales (4.5).

En revanche, la signature est explicitement appelée pour les types entiers signés (paragraphe 2) et les types entiers non signés (paragraphe 3).

Maintenant, pour les traits is_signed et is_unsigned . Tout d’abord, les traits sont toujours bien définis, mais seulement intéressants pour les types arithmétiques. bool est un type arithmétique et is_signed::value est défini (voir Tableau 49) sous la forme T(-1) < T(0) . En utilisant les règles de conversion booléenne et les conversions arithmétiques standard, nous voyons que c'est false pour T = bool (parce que bool(-1) est true , ce qui convertit en 1 ). De même, is_unsigned::value est défini comme T(0) < T(-1) , ce qui est true pour T = bool .

is_unsigned est défini dans [meta.unary.comp] / 2 comme

Si is_arithmetic::value est true , le même résultat que
bool_constant::value ; sinon, false

bool est clairement un type arithmétique (intégrale). Considérons maintenant [conv.bool] / 1:

Une valeur nulle, une valeur de pointeur nul ou une valeur de pointeur de membre nul est convertie en false ; toute autre valeur est convertie en true .

Ie bool(0) < bool(-1) est équivalent à false < true , et ce dernier est valable puisque les valeurs sont promues à 0 et 1 , respectivement.

Ainsi, is_unsigned::value est true (et inversement, is_signed est false ), car les valeurs booléennes correspondent aux valeurs non signées 0 et 1 lors des opérations arithmétiques. Cependant, il n'est pas vraiment judicieux d'évaluer la signature de bool , et encore moins de faire make_unsigned sur elle, car elle ne représente pas des entiers, mais plutôt des états.


: Le fait que ce modèle soit applicable à bool en premier lieu est déterminé par le fait que sa clause Requirement est inexistante, bool n'étant pas un type incomplet ([res.on.functions] / (2.5)) et aucune autre exigence n'étant mentionné dans [meta.rqmts] pour UnaryTypeTraits .

Oui, c’est bien défini, comme tout autre trait de type unaire.

C ++ 14 (n4140) 20.10.4 / 2 Mandats “Caractères de type unaire”:

Chacun de ces modèles doit être un UnaryTypeTrait (20.10.1) avec une caractéristique de true_type de true_type si la condition correspondante est vraie, sinon false_type .

20.10.1 / 1:

UnaryTypeTrait décrit une propriété d’un type. Ce doit être un modèle de classe qui prend un argument de type modèle et, éventuellement, des arguments supplémentaires qui aident à définir la propriété en cours de description. Il doit être CopyConstructible , directement ou indirectement, à partir de sa caractéristique de base, qui est une spécialisation de la constante de modèle integral_constant (20.10.3), avec les arguments de la propriété integral_constant définie par les exigences de la propriété particulière. étant décrit. Les noms de membre de la BaseCharacteristic ne doivent pas être masqués et doivent être disponibles sans ambiguïté dans UnaryTypeTrait.

Il en résulte que la construction std::is_unsigned::value doit être bien définie pour tout type T , que le concept de “signature” ait ou non un sens pour le type.

Oui, il est bien défini et le résultat devrait être std::is_unsigned::value == true

La documentation de std::is_signed indique

Si T est un type arithmétique signé , fournit la valeur constante du membre égale à true. Pour tout autre type, la valeur est fausse.

Donc, si vous regardez std::is_arithmetic

Si T est un type arithmétique (c’est-à-dire un type intégral ou un type à virgule flottante ), la valeur constante du membre est égale à true. Pour tout autre type, la valeur est fausse.

Ce qui conduit finalement à std::is_integral

Vérifie si T est un type intégral. Fournit la valeur de constante du membre qui est égale à true, si T est le type bool , char , char16_t , char32_t , wchar_t , short , int , long , long long ou tout type d’entier étendu défini par l’implémentation, y compris et variantes qualifiées cv. Sinon, la valeur est égale à false.

Fait intéressant, il existe une autre fonction std::numeric_limits::is_signed qui indique

La valeur de std::numeric_limits::is_signed est true pour tous les types arithmétiques signés T et false pour les types non signés. Cette constante est significative pour toutes les spécialisations.

Où la spécialisation pour bool est listée comme false , ce qui confirme également que bool est considéré comme non signé.