10
votes

Y a-t-il un moyen de rendre le type `Enum` pour être non signé?

y a-t-il un moyen de faire enum code> de type pour être non signé? Le code suivant me donne un avertissement sur la comparaison signée / non signée.

enum EEE {
    X1 = 1,
    XN = 18446744073709551615LL
    // I've tried XN = UINT_MAX (in Visual Studio). Same warning.
};


5 commentaires

Liée, mais pas en double: Stackoverflow.com/Questtions/2579230/...


Stackoverflow.com/Questtions/159034


@SBI, ce n'est pas un duplicata, car la norme C ++ donne un indice sur la manière de changer de type insignifiant sur Int. Et j'essaie d'utiliser ça.


@Sbi, la prochaine fois, veuillez copier et coller l'URL entière . Le débordement de la pile va abréger à ce que vous avez posté de toute façon, mais lorsque vous inclurez le tout, nous pouvons obtenir un embout d'outil indiquant le titre de la question (en réalité, le reste de l'URL) sans avoir à visiter le lien. Comparez le vôtre avec le commentaire de James.


@ROB: Tu as raison, ça aurait été mieux dans ce cas. J'ai eu l'habitude de ressortir les parties redondantes parce que la salle des commentaires est limitée.


6 Réponses :


1
votes

Selon est C ++ Enums signé ou non signé? Votre compilateur doit choisir si Enum est signé ou non, bien qu'il y ait des commentaires qui disent que, dans C ++ 0x, vous pourrez spécifier qu'il est non signé.


0 commentaires

2
votes

pas dans la version actuelle de C ++. C ++ 0x fournira des énums fortement dactylographiés.

Pour le moment, vous pouvez utiliser si (static_cast (t) pour supprimer l'avertissement.


1 commentaires

J'essaie d'éviter plus static_cast s.



8
votes

Vous pouvez essayer: xxx

sans le u , le littéral entier est signé.

(Ceci assume bien sûr vos supports de mise en œuvre long long ; Je suppose que cela fait depuis la question initiale utilise ll ; sinon, vous pouvez utiliser Ul pour un long ).


5 commentaires

Cela fonctionne dans GNU C ++, mais pas dans Visual Studio. Semble être un bogue dans vs Ce code est correct aussi, mais mieux utiliser uint_max .


@James, ah, en effet. Si vous le faites avec "LLU" au lieu de "U" comme je l'ai fait, il ne peut plus choisir "longtemps". Un bon moyen de contourner le libellé peu clair de ce que signifie "plus grand"! Je vous évierais si vous utilisez une macro limite ou -1ull (ou -1ul en C ++ 03 ou longue implémentation longue) :)


ullong_max ne fonctionne pas dans VC ++ aussi. Je pense que le compilateur pense qu'il peut générer du code 128 bits.


@Johannes: Merci de me rappeler le tour de -1; Cela avait glissé mon esprit.


@Kirill: Quelle que soit la valeur que je donne un énumérateur, l'énumération a toujours une taille de quatre octets au VS2008. : - /



0
votes

Pourquoi pas

if ( size_t( t ) < x )


3 commentaires

Comment savez-vous que vos valeurs ENUM pour l'ENUM EEE sont non signés? Ils ressemblent à des Ints pour moi.


@chollida, l'objectif ultime était de se débarrasser de l'avertissement, de ne pas le faire non signé, je soupçonnerais. Son chemin réussit.


@COHOLIDA: La question est de savoir comment rendre le type d'enums non signé. Cela impliquerait qu'il ne mettrait pas de valeurs négatives dans, ou il veut un arithmétique modulo s'il le fait.



2
votes

Vous pouvez également surcharger les opérateurs si vous souhaitez le comparer

/* everything "shorter" than "int" uses either int or unsigned */
bool operator<(EEE e, int u) {
  return (int)e < (int)u;
}

bool operator<(EEE e, unsigned u) {
  return (unsigned int)e < (unsigned int)u;
}


bool operator<(EEE e, long u) {
  return (long)e < (long)u;
}

bool operator<(EEE e, unsigned long u) {
  return (unsigned long)e < (unsigned long)u;
}

/* long long if your compiler has it, too */


7 commentaires

Plutôt verbose, mais obtient le travail si vous cherchez à éviter Static_cast


-1U ? essayez-vous d'appliquer un opérateur minus unaire au type non signé? Devrait-il changer le type à signé?


@Kirill, il restera non signé mais changera sa valeur sur uint_max . Donc, vous n'avez pas besoin de l'en-tête des limites.


J'ai supprimé le "truc" avec le uint_max parce que je pense que "plus grand" signifie en réalité la valeur "Tailleof" - comme dans "Taille du type" (après avoir demandé à Digregor). "long" pourrait être la même taille de "non signé INT" et pourrait donc choisir "longtemps". Le seul moyen sûr semble être d'utiliser la solution @james et d'utiliser -1ull si vous voulez rester avec l'ENUM sans la surcharge et les trucs de l'opérateur.


-1UL semble prometteur, mais dans Visual Studio, cela ne fonctionne pas non plus. Je vais essayer de poster des bugs dans le suivi vs bug.


Bien sûr, vous auriez alors besoin de mettre en œuvre tous les autres opérateurs de comparaisons (boost.opérators pourrait aider) ... Pourriez-vous vous éloigner avec un modèle avec un modèle utilisant boost :: activer_if et boost :: is_signé / boost :: is_unsigned (ou peut-être juste boost :: is_integal )?


@Matthieu Yeah je suppose que nous pourrions sortir avec un gabarit comme ça.



1
votes

3 commentaires

@ Kirillv.lyadvinsky: vraiment? Cela devrait. MSVC dit qu'il compile cela depuis MSVC2005.


J'ai cherché non signé dans la référence, mais cela ne s'affiche pas comme si vous fournissez ci-dessus. non signé n'est utilisé qu'une fois dans une phrase. Êtes-vous certain que la référence est correcte?


@JWW bien, cette phrase explique comment il devrait être utilisé. La référence à Type est une référence à la déclaration schématique au sommet de l'article: Enum [tag] [: Type] ... il dis donc que < Code> Type Il peut y avoir n'importe quel type d'intégral signé sous scalaire ou non signé. Ceci devrait fonctionner certainement. Il se compile pour moi sur VS 2010, mais cela donne un avertissement C4480 (extension non standard utilisée: spécifiant le type sous-jacent pour ENUM).