2010-04-28 19 views
10

Gibt es eine Möglichkeit, den Typ enum unsigniert zu machen? Der folgende Code warnt mich vor einem signierten/unsignierten Vergleich.Gibt es eine Möglichkeit, den `enum` -Typ vorzeichenlos zu machen?

enum EEE { 
    X1 = 1 
}; 

int main() 
{ 
    size_t x = 2; 
    EEE t = X1; 
    if (t < x) std::cout << "ok" << std::endl; 

    return 0; 
} 

Ich habe versucht, Compiler zu zwingen, für Enum unsigned zugrunde liegenden Typen zu verwenden, mit dem folgenden:

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

Aber das gibt immer noch die Warnung.


Ändern konstant UINT_MAX macht es in GNU C++ arbeitet als den Standard entsprechend werden soll. Scheint ein Fehler in VS zu sein. Danke an James für einen Hinweis.

+0

Verwandte, aber nicht duplizieren: http://stackoverflow.com/questions/2579230/signedness-of-enum-in-c-c99-c-cx-gnu-c -gnu-c99 –

+0

http://StackOverflow.com/Questions/159034/ – sbi

+2

@SBI, das ist kein Duplikat, weil C++ Standard einen Hinweis darauf gibt, wie man den Datentyp "Unlying" in "Unsigned Int" ändert. Und ich versuche das zu benutzen. –

Antwort

8

Sie könnten versuchen:

enum EEE { 
    X1 = 1, 
    XN = -1ULL 
}; 

Ohne die U wird die Ganzzahlliteral unterzeichnet.

(Dies setzt natürlich voraus, Ihre Implementierung unterstützt long long, ich nehme an, es tut, da die ursprüngliche Frage LL verwendet, andernfalls Sie UL für eine long verwenden können).

+0

Dies funktioniert in GNU C++, aber nicht in Visual Studio. Scheint ein Fehler in VS zu sein. Dieser Code ist auch korrekt, aber besser 'UINT_MAX' zu verwenden. –

+0

@James, Ah, tatsächlich. Wenn Sie es mit "LLU" anstatt nur mit "U" tun, wie ich es getan habe, kann es nicht mehr "lang" wählen. Guter Weg, um den unklaren Wortlaut dessen zu umgehen, was "größer" bedeutet! Ich würde upvote, wenn Sie ein Limit-Makro oder "-1ULL" (oder "-1UL" in C++ 03 oder lange lange Implementierung) verwenden :) –

+0

'ULLONG_MAX' funktioniert nicht in VC++ auch. Ich denke, der Compiler glaubt, er könne 128-Bit-Code erzeugen. –

1

Nach Are C++ enums signed or unsigned? kann Ihr Compiler wählen, ob enum signiert ist oder nicht, obwohl es einige Kommentare gibt, die sagen, dass Sie in C++ 0x angeben können, dass es nicht signiert ist.

2

Nicht in der aktuellen Version von C++. C++ 0x wird stark typisierte Enums bereitstellen.

Zur Zeit können Sie if (static_cast<size_t>(t) < x) verwenden, um die Warnung zu entfernen.

+2

Ich versuche, zusätzliche 'static_cast's zu vermeiden. –

0

Warum nicht

enum EEE { 
    X1 = 1, 
    x = 2 // pick more descriptive name, a'course 
}; 

oder

if (size_t(t) < x) 
+2

Woher wissen Sie, dass Ihre Enum-Werte für das Enum-EEE nicht signiert sind? Sie sehen aus wie Intarsien für mich. – chollida

+0

@chollida, das ultimative Ziel war es, die Warnung loszuwerden, nicht um es unsigniert zu machen, würde ich vermuten. Sein Weg erreicht das. –

+0

@cohollida: Die Frage ist, wie man den Enum-Typ vorzeichenlos machen kann. Das würde bedeuten, dass er keine negativen Werte eingeben wird, oder er möchte modulo rechnen, wenn er es tut. – Potatoswatter

2

Sie könnten auch die Betreiber überlasten, wenn Sie es

enum EEE { 
    X1 = 1 
}; 

bool operator<(EEE e, std::size_t u) { 
    return (int)e < (int)u; 
} 

vergleichen wollen auch immer Sie diesen Tanz für jede ganze Zahl zu tun haben Tippen Sie auf die rechte Seite. Andernfalls, wenn Sie e < 2 tun, wäre es mehrdeutig: Der Compiler könnte Ihre operator< genau die linke Seite genau verwenden, aber eine Konvertierung auf der rechten Seite, oder seine eingebauten Operator, eine Förderung für die linke Seite und die richtige Seite genau .

So letztlich würde ich die folgenden Versionen setzen:

/* 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 */ 

Nicht sehr schön :) Aber zumindest der Benutzer Ihrer Aufzählung ist leicht geht. Wenn Sie jedoch nicht gegen gewöhnliche int aber gegen einen bedeutungsvollen Wert vergleichen möchten, würde ich tun, was ein anderer Kerl vorgeschlagen, und fügen Sie einen anderen Enumerator, der als Wert 2 hat, und nennen Sie es. Auf diese Weise werden Warnungen auch weggehen.

+0

Eher ausführlich, aber erledigt die Arbeit, wenn Sie versuchen, static_cast –

+0

'-1U' zu vermeiden? Versuchen Sie, einen unären Minusoperator auf einen unsignierten Typ anzuwenden? Sollte das den Typ zu unterschrieben ändern? –

+0

@Kirill, es bleibt 'unsigned', ändert aber seinen Wert in 'UINT_MAX'. Sie brauchen also den Limit-Header nicht. –

1

Per C++ Enumeration Declarations on MSDN:

enum EEE : unsigned { 
    X1 = 1 
}; 
+0

es kompiliert nicht –

+0

@ KirillV.Lyadvinsky: wirklich? Es sollte. MSVC sagt, dass es das seit MSVC2005 kompiliert. –

+1

Ich suchte nach *** unsigned *** in der Referenz, aber es zeigt sich nicht wie Sie oben angeben. *** unsigned *** wird nur einmal in einem Satz verwendet. Sind Sie sicher, dass die Referenz richtig ist? – jww

Verwandte Themen