enum class als Index für ein Array geht nicht ohne Cast



  • Hi liebe C++ Fachmänner,

    ich so als C++ Neueinsteiger verstehe nicht warum man nicht eine enum class mit dem Datentyp int direkt als Index für ein Array nehmen kann. Warum muss ich ein int extra zu einem int casten um die enum class als Index zu verwenden?

    int main()
    {
    	enum class INDEX : int { EINS, ZWEI, DREI, POLIZEI, END } index_{ INDEX::EINS }; // enum class mit dem Datentyp int 
    
    	int meinArray[INDEX::END]{ 0 }; // geht nicht da angeblich nicht vom Datentyp int 
    	//error C3411:  'main::INDEX' is not valid as the size of an array as it is not an integer type
    
    	int meinArray[static_cast<int>(INDEX::END)]{ 0 }; // mit extra Cast von int zu int geht es 
    }
    
    


  • Das geht nicht ohne cast weil eine enum class nicht implizit in ihren underlying type konvertierbar ist.

    [dcl.enum/10]



  • Ah ok danke für die schnelle Lösung.



  • Das ist auch eigentlich die einzige Daseinsberechtigung für scoped enums.

    Btw. zwischen "an integer type" und int sollte man schon unterscheiden. char is an integer type ...
    Btw. 2: Gewohn dir blanke Arrays ab. std::array<> ftw.



  • Danke, wenn das std::array<> keinen Nachteil von der Geschwindigkeit hat, dann nehme ich das gern.



  • @chris4cpp sagte in enum class als Index für ein Array geht nicht ohne Cast:

    wenn das std::array<> keinen Nachteil von der Geschwindigkeit hat

    Nein.

    @chris4cpp sagte in enum class als Index für ein Array geht nicht ohne Cast:

    // mit extra Cast von int zu int geht es 
    

    "von int zu int" ... das wäre übrigens auch für unscoped enums eine Fehlannahme. Ein

    enum foo { ... };
    

    ist ein Typ für sich selbst.



  • Ja, dachte die Werte kann ich nutzen da man extra noch einen Datentyp mit angeben kann für die enum (enum class <bezeichner> : <datentyp>)

    Gibt es denn in C++ eine andere Möglichkeit einen Index für ein Array mit Namen zu versehen?



  • Konstanten? Die Werte eines enums?



  • Also entweder mit enum class und casten oder nur enums nehmen?



  • Aus den Werten einer scoped enum (= enum class) wird ohne Gewalt kein integer. Nicht mal mit böse anstarren (probiert. stundenlang. geht wirklich nicht.).

    @chris4cpp sagte in enum class als Index für ein Array geht nicht ohne Cast:

    nur enums nehmen?

    ja.



  • Jezt mal ne ganz blöde frage.
    Was bringt einem eine enum class ?
    Hört sich für mich danach an das man eine klasse mittels Zahlenwert aus diesem enum aufrufen kann



  • Vergiss das class bei enum class. Das ist keine class. Man hat nur ein Schlüsselwort gebraucht um dieses Ding mit C++11 einzuführen und class wurde eben genommen weil die Wahrscheinlichkeit daß es mit anderen Dingen kollidiert ziemlich gering ist. Nebenbei: Man kann auch für unscoped enums seit C++11 den underlying type explizit angeben.

    Basically ist ein enum class auch nichts anderes als ein enum (ohne das böse c-wort). Nur daß es sich eben nicht bei schief anschauen in einen integer auflöst. Sinn dahinter ist mehr Typsicherheit. Deshalb funktionieren so typische (classic) enum-Sachen wie Bitflags mit enum class auch nicht (ohne blöde Operatorüberladungen).

    enum foo {
        bar = 0x01,  // 0b0001
        baz = 0x02,  // 0b0010
        qux = 0x04   // 0b0100
    };
    
    // ...
    
    int flags{ bar | baz };  // bar und baz setzen
    flags |= qux;            // qux auch noch
    flags &= ~bar;           // bar loeschen
    

    // edit: Ach so, ein anderer Grund eine scoped enum zu nehmen ist, daß die identifier eben scoped sind und nicht den globalen Namensraum zumüllen. Andreaseits kann man das auch mit einer unscoped enum haben wenn man sie in einen namespace steckt.

    namespace dont_touch {  // i'll slap your fingers!
    	enum _my_very_very_secret_foo {
    		bar = 0x01,  // 0b0001
    		baz = 0x02,  // 0b0010
    		qux = 0x04   // 0b0100
    	};
    }
    
    typedef dont_touch::_my_very_very_secret_foo foo;  // oder eben eine using declaration
    
    // ...
    
    int flags{ foo::bar | foo::baz };  // bar und baz setzen
    flags |= foo::qux;                 // qux auch noch
    flags &= ~foo::bar;                // bar loeschen
    
    foo f{ foo::baz };
    

    Jetzt könnte natürlich ein phöser phöser Mensch meinen schönen Namespace noch mit anderen Bezeichnern verpesten. But hey, shit happens.

    // edit: added one more "very".


Anmelden zum Antworten