enum zu string



  • Gibt es eine bessere Lösung?
    Mit Makros hab ichs nicht hinbekommen und ohne wüsste ich nicht, wie man an die Zuordnung enum-wert und name kommt -.-

    Hier ein kleines Beispiel:

    namespace character
    {
    	enum T
    	{
    		A = 0,
    		B,
    		C
    	};
    
    	char names[] =
    	{
    		'A',
    		'B',
    		'C'
    	};
    }
    
    struct letter_t
    {
      charater::T letter;
    };
    
    std::ostream& operator<< (std::ostream& os, const letter_t& these)
    {
      return os << character::names[these.letter] << std::endl;
    }
    

    danke schon mal : >



  • hallo

    wenn es genau um das beispiel gehen sollte wuerde ich es so machen

    namespace character
    {
        enum T
        {
            A = 0,
            B,
            C
        };
    
        struct names
        {
           static char get(T value) { return static_cast<char>(value) + 'A'; }
        };
    }
    
    struct letter_t
    {
      charater::T letter;
    };
    
    std::ostream& operator<< (std::ostream& os, const letter_t& these)
    {
      return os << character::names::get[these.letter] << std::endl;
    }
    

    aber ich schaetz mal das das nicht der fall sein wird 🙂

    Meep Meep


  • Administrator

    unskilled schrieb:

    Gibt es eine bessere Lösung?

    Am besten gar nicht erst machen 😃

    unskilled schrieb:

    Mit Makros hab ichs nicht hinbekommen und ohne wüsste ich nicht, wie man an die Zuordnung enum-wert und name kommt -.-

    Mit Makros köntne man es ca. so machen:

    #include <iostream>
    
    #include <boost/preprocessor/seq/enum.hpp>
    #include <boost/preprocessor/seq/transform.hpp>
    
    #define MACRO_TRANSFORM_SEQUENCE(s, data, elem) #elem
    
    #define MACRO_CREATE_NAMED_ENUM(enumname, arrayname, seq) \
    	enum enumname { BOOST_PP_SEQ_ENUM(seq) };             \
    	char const* const arrayname[] = { BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(MACRO_TRANSFORM_SEQUENCE, _, seq)) };
    
    MACRO_CREATE_NAMED_ENUM(Glyphs, GlyphsName, (Alpha)(Beta)(Gamma))
    
    int main()
    {
    	std::cout << GlyphsName[Beta] << std::endl;
    
    	return 0;
    }
    

    Davon rate ich allerdings ab, da es schlecht lesbar ist und die IDE Tools mit dem Zeug meistens nicht sinnvoll umgehen können. Lieber von Hand hinschreiben. 😉

    Grüssli



  • @Dravere:
    Japp, hübsch ist es wirklich nicht 😛
    Ich hab mich auch noch immer nicht mit dem ganzen Boost-PP-Zeugs anfreunden können - aber vll ists ja nicht mehr so extrem hässlich und unleserlich, wenn man es mal wirklich brauchte und sich damit auseinander setzen musste 😉

    @Meep Meep: Ok, da war das Bsp. wohl zu einfach gewählt... ^^ Außerdem ist das auch nicht ganz standardkonform - wenn schon, dann würd ich das so machen, wenns so einfach wäre:

    enum T
    {
     A = 'A',
     B = 'B',
     C = 'C'
    };
    
    std::ostream& operator<< (std::ostream& os, T these)
    {
      return os << static_cast<char>(these);
    }
    

    Danke, dann lass ich es wohl so, wie es bisher ist... ^^

    bb



  • hi

    hab noch einen link gefunden. vielleicht bringt er dich ja auf eine idee
    http://de.how-to.mobi/index.php?id=217549

    Meep Meep



  • Danke, aber naja - da ist immer viel zu viel drum rum - das lohnt sich nicht so wirklich... ^^

    übrigens:

    struct Flintstones { 
       enum E { 
          Fred, 
          Barney, 
          Wilma 
       }; 
    }; 
    Flintstones::E fred = Flintstones::Fred; 
    Flintstones::E barney = Flintstones::Barney;
    

    welchen vorteil hat das denn bitte?

    bb


  • Administrator

    unskilled schrieb:

    welchen vorteil hat das denn bitte?

    Enums "entleeren" sich immer automatisch im aktuellen Scope. So kann man dies "verhindern", bzw. begrenzen. Ich nehme meistens einen namespace . Wenn ich mich recht erinnere, wird es im neuen Standard dazu eine bessere Möglichkeit geben. Müsste ich aber zuerst nachschauen.

    Grüssli



  • Dravere schrieb:

    Wenn ich mich recht erinnere, wird es im neuen Standard dazu eine bessere Möglichkeit geben.

    Du meinst enum class.



  • @Dravere: Ja, das ist mir klar - deshalb ja auch der namespace in meinem Bsp. drum rum

    Ich meinte eigtl. das hier:

    Flintstones::E fred = Flintstones::Fred;
    Flintstones::E barney = Flintstones::Barney;
    

    aber wenn ich noch mal so drüber nachdenke, könnte das auch schon das Bsp. sein und nicht mehr zum Vorschlag an sich gehören... ^^



  • Eine vielleicht etwas eigenwillige Lösung, aber dürfte in den meisten Fällen den Zweck erfüllen:

    #define ENUM(name) typedef const char* name; name
    #define ENTRY(e) e = #e
    
    // ...
    
    ENUM(name) ENTRY(fritz), ENTRY(franz), ENTRY(heinz);
    
    // ...
    
    name n = franz;
    std::cout << n;
    

    Über Lesbarkeit und Eleganz kann man sicher streiten, kann man sicher auch noch verfeinern, aber man hat zumindest enum-nahes Verhalten.



  • switch ( enum )	{
    		case enum-1	: o << "enum-1";	break;
    		case enum-2	: o << "enum-2";	break;
    			...
    		default		: o << "error";
    		}
    

    So mach ich das, das ist einfach, billig und leicht verständlich.
    Falls Dein Problem richtig verstanden wurde 🙂

    tschüß
    Troll.Soft



  • Troll.Soft schrieb:

    switch ( enum )	{
    		case enum-1	: o << "enum-1";	break;
    		case enum-2	: o << "enum-2";	break;
    			...
    		default		: o << "error";
    		}
    

    So mach ich das, das ist einfach, billig und leicht verständlich.
    Falls Dein Problem richtig verstanden wurde 🙂

    tschüß
    Troll.Soft

    Das sieht für mich auch verständlich und übersichtlich aus. An dieser Stelle hat man dann zwar doppelten Aufwand, da der StringText und das eigentliche enum getrennt von einander liegen und man so auch mal vergessen kann, das es das hier gibt. Aber was besseres habe ich bisher noch nicht gesehen.



  • freak4fun schrieb:

    An dieser Stelle hat man dann zwar doppelten Aufwand, da der StringText und das eigentliche enum getrennt von einander liegen und man so auch mal vergessen kann, das es das hier gibt.

    Löscht man später einen Enumwert heraus, meckert der Compiler.
    Fügt man einen Enumwert hinzu und vergißt ihn auszugeben gibt es über default: einen kräftigen Warnhinweis.



  • Eine Assertion wäre imho im Default-Zweig deutlich sinnvoller.

    default: assert(false);
    


  • Man kann für die case-Zweige ein Makro bauen, so das man nicht alles doppelt schreiben muss.



  • Meiner Meinung nach ist das ein Designfehler, wenn so etwas gebraucht wird.



  • Finde ich z.B. für Debug-Ausgaben sinnvoll!



  • finder schrieb:

    Finde ich z.B. für Debug-Ausgaben sinnvoll!

    Jemals was von Debugger gehört? ^^

    Aber ja, das ist ein Argument.



  • Ich empfinde diese Variante als wesentlich sinniger:

    enum T
        {
            A = 0,
            B,
            C
        };
    
        char names[] =
        {
            'A',
            'B',
            'C'
        };
    


  • Janjan schrieb:

    Eine Assertion wäre imho im Default-Zweig deutlich sinnvoller.

    default: assert(false);
    

    Aber nicht in der Release.


Anmelden zum Antworten