web-dev-qa-db-fra.com

Est !! un moyen sûr de convertir bool en C++?

[Cette question est liée à/mais pas la même chose que celle-ci .]

Si j'essaie d'utiliser les valeurs de certains types comme expressions booléennes, je reçois un avertissement. Plutôt que de supprimer l'avertissement, j'utilise parfois l'opérateur ternaire (?:) pour convertir en bool. L'utilisation de deux opérateurs non (!!) semble faire la même chose.

Voici ce que je veux dire:

typedef long T;       // similar warning with void * or double
T t = 0;
bool b = t;           // performance warning: forcing 'long' value to 'bool'
b = t ? true : false; // ok
b = !!t;              // any different?

Alors, la technique du double-pas fait-elle vraiment la même chose? Est-ce plus ou moins sûr que la technique ternaire? Cette technique est-elle également sûre avec les types non intégraux (par exemple, avec void * ou double pour T)?

Je ne demande pas si !!t est un bon style. Je demande si c'est sémantiquement différent de t ? true : false.

50
jwfearn

L'argument du! L'opérateur et le premier argument de l'opérateur ternaire sont tous deux implicitement convertis en bool, alors !! et?: sont les décorations idiotes et stupides de la distribution? Je vote pour 

b = (t != 0);

Pas de conversions implicites.

83
fizzer

Sinon, vous pouvez faire ceci: bool b = (t != 0)

41
Dima

Prudent!

  • Un booléen concerne la vérité et la fausseté.
  • Un entier est à propos de nombres entiers.

Ce sont des concepts très distincts:

  • La vérité et la fausseté, c'est décider.
  • Les chiffres consistent à compter des choses.

Pour relier ces concepts, cela doit être fait explicitement. J'aime mieux la version de Dima:

b = (t != 0);

Ce code dit clairement: Comparez deux nombres et stockez la valeur de vérité dans un booléen.

31
edgar.holleis

Toutes les techniques valides généreront le même code.

Personnellement, je viens de désactiver l'avertissement pour pouvoir utiliser la syntaxe la plus propre. Je ne m'inquiète pas de faire accidentellement l'incident.

6
Mike F


Oui c'est sûr.


0 est interprété comme faux, tout le reste est vrai,
donc! 5 apparaît comme un faux
! 0 est vrai
alors !! 5 sort comme vrai

6
EvilTeach

Je n'utiliserais pas:

bool b = !!t;

C'est le moyen le moins lisible (et donc le plus difficile à maintenir)

Les autres dépendent de la situation.
Si vous convertissez uniquement dans une expression booléenne.

bool b = t ? true : false;
if (b)
{
    doSomething();
}

Ensuite, je laisserais la langue le faire pour vous:

if (t)
{
    doSomething();
}

Si vous stockez réellement une valeur booléenne. Alors d'abord, je me demanderais pourquoi vous avez un long rôle dans les premiers endroits qui nécessite le casting. En supposant que vous ayez besoin de la valeur long et bool, je considérerais tout ce qui suit en fonction de la situation.

bool  b = t ? true : false;      // Short and too the point.
                                 // But not everybody groks this especially beginners.
bool  b = (t != 0);              // Gives the exact meaning of what you want to do.
bool  b = static_cast<bool>(t);  // Implies that t has no semantic meaning
                                 // except as a bool in this context.

Résumé: Utilisez ce qui donne le plus de sens au contexte dans lequel vous vous trouvez.
Essayez de rendre évident ce que vous faites

5
Martin York

Je recommande de ne jamais supprimer cet avertissement et de ne jamais utiliser un c cast (bool) pour le supprimer. Les conversions ne peuvent pas toujours être appelées comme vous le supposez.

Il existe une différence entre une expression évaluée comme étant vraie et un booléen de cette valeur.

Tous les deux !! et ternary prend l'habitude de s'y habituer, mais fera le même travail si vous ne voulez pas définir de types internes avec des conversions surchargées à bool.

L'approche de Dima est également satisfaisante, car elle attribue la valeur d'une expression à un bool.

3
tabdamage

Si l'avertissement vous inquiète, vous pouvez également forcer le casting: bool b = (bool)t;

2
warren

Je déteste vraiment !! t !!!!!!. C’est la pire chose à propos de C et C++, la tentation d’être trop intelligent de moitié avec votre syntaxe.

bool b (t! = 0); // Est la meilleure façon à mon humble avis, il montre explicitement ce qui se passe.

2
Jim In Texas

!! peut être compact, mais je pense que c'est inutilement compliqué. Mieux vaut désactiver l'avertissement ou utiliser l'opérateur ternaire, à mon avis.

1
Kristopher Johnson

La comparaison avec 0 ne marche pas très bien. Ce qui revient - pourquoi !! ternaire?

class foo { public: explicit operator bool () ; };

foo f;

auto a = f != 0; // invalid operands to binary expression ('foo' and 'int')
auto b = f ? true : false; // ok
auto c = !!f; // ok
0
Jay K

Je voudrais utiliser b = (0! = T) - au moins toute personne saine d'esprit peut le lire facilement. Si je voyais le code double dans le code, je serais assez surpris.

0
Alex

!! est utile uniquement lorsque vous utilisez une expression booléenne de manière arithmétique, par exemple:

c = 3 + !!extra; //3 or 4

(Dont le style est une discussion différente.) Quand tout ce dont vous avez besoin est une expression booléenne, le !! est redondant. L'écriture

bool b = !!extra;

a autant de sens que:

if (!!extra) { ... }
0
aib

Désactiver l'avertissement.

Écrivez pour la clarté d'abord; puis profil; puis optimisez pour la vitesse, si nécessaire.

0
Jay Bazuzi