switch case für einen string



  • Hallo zusammen,

    folgende Funktion habe :

    void convertToEnum(const std::string& strGender)
    { 	
    	if(strGender != "male" || strGender != "female")
    	{
           // mach....		
    	}
    	else {
    		switch(strGender){ // warum geht es nicht 
    			case "male":
    			//...
    			break;
    			case "female":
    			//...
    			break;
    			default:
    			break;
    		}
    	}
    }
    
    

    danke



  • @Saheb Meldet der Compiler irgendwas?
    Evtl auch Warnungen?

    Das // mach.... wird immer gemacht.



  • @DirkB sagte in switch case für einen string:

    @Saheb Meldet der Compiler irgendwas?
    Evtl auch Warnungen?

    Das // mach.... wird immer gemacht.

    Ja, und dementsprechend wird der else-Zweig niemals ausgeführt ...
    Davon abgesehen geht doch alles, sprich:
    'geht nicht' ist eine beschissene Fehlerbeschreibung!



  • @Belli sagte in switch case für einen string:

    'geht nicht' ist eine beschissene Fehlerbeschreibung!

    Aber die Antwort ist recht einfach: "Weil etwas falsch ist."
    Kommt aber nicht so gut an.



  • @Saheb der Ablauf ist auch etwas merkwürdig.

    Erst ein (fehlerhafter) Test ob die Werte gültig sind, dann ein switch mit einem leeren default-Zweig.



  • Seit wann funktionieren Strings in switch-Anweisungen???

    Man kann zwar mittels constexpr etwas basteln (C++11 Switch on String Literals), aber äquivalent mit einem String-Compare ist der Hash-Vergleich dann nicht.



  • Man kann auch über eine Liste Suchen und dann den Index für die switch benutzen, ist mMn. immer noch übersichtlicher als gefühlte 1000 if then else zu schreiben. Alles ohne constexpr gebastel und gut erweiterbar.



  • This post is deleted!




  • Den anderen hash aus dem Link kenne ich nicht, ich habe noch das hier gefunden in altem Code:

    /// Contains implementation of FNV-1A hash.
    
    #include <cstdint>
    #include <string_view>
    
    constexpr std::uint32_t fnv32Seed{2166136261u};
    constexpr std::uint32_t fnv32Prime{16777619u};
    
    constexpr std::uint32_t fnv32(std::string_view str) {
        std::uint32_t hash{fnv32Seed};
        for (char ch : str) {
            hash = fnv32Prime * (hash ^ ch);
        }
        return hash;
    }
    

    Verwendung wäre ähnlich:

    switch (fnv32(myStr)) {
        case fnv32("Test"):
            // ...
            break;
        // usw.
    }
    

    Für Deinen Anwendungsfall (strToEnum), ist der Ansatz vermutlich schon ziemlich gut. Ansonsten könntest Du mal bei LLVM nachschauen, die haben auch ein StringSwitch, das ist sicherlich nicht schlecht und ich glaube etwas flexibler als ein reiner Hash-Vergleich. Wenn es um Performance geht (Du nimmst C++, also i.d.R. lautet die Antwort: ja), am Ende einfach direkt Messen.

    Edit: Meine Güte, ich habe mal im Forum nach "string switch" gesucht, das tut ja weh wie oft das schon gefragt wurde...



  • @HarteWare
    danke



  • @HarteWare sagte in switch case für einen string:

    Edit: Meine Güte, ich habe mal im Forum nach "string switch" gesucht, das tut ja weh wie oft das schon gefragt wurde...

    Ja ich hab dazu auch mal ein post aufgemacht.
    Ich finde das ist ein Feature das C++ fehlt.



  • @5cript
    Switch auf Strings ist halt etwas das in C++ so gar nicht einfach umzusetzen wäre weil std::string und std::string_view keine eingebauten Typen sind. Klar, man könnte es irgendwie hinbiegen. Vermutlich wäre die optimale Lösung es ähnlich wie bei ranged based for zu machen und zu sagen alles was passende hash(x) und x == y hat wird bei switch unterstützt.

    Das wäre natürlich ein cooles Feature.



  • @hustbaer
    Naja range based for funktioniert ja auch mit begin und end Konventionen.
    Prinzipiell sehe ich nicht das Problem dass jemand cleveres sich was cleveres ausdenkt 😃
    Also, wem zwingen wir jetzt auf das Proposal zu schreiben mit allem drum und dran? 😛



  • @5cript sagte in switch case für einen string:

    Also, wem zwingen wir jetzt auf das Proposal zu schreiben mit allem drum und dran? 😛

    Ich kann leider gar niemanden zwingen irgendwas zu tun. Aber ich kann ja mal @Columbo hier taggen. Im sehr unwahrscheinlichen Fall dass es ihn ausreichend interessiert und er genug Zeit übrig hat... ich würde ihm auf jeden Fall zutrauen das hinzubekommen.



  • Ich möchte hier mal nach dem Usecase für ein String-Switch fragen.

    Meistens gibt es bessere Lösungen wie z.B. eine Map (oder etwas mapartiges), wo man von dem String auf die gewünschte Funktionalität zeigt.

    Erlaubt man beliebige Klassen, dann wird man auch kaum feststellen können, wann ein neues "string-enum"-Element hinzugefügt wird und an welchen Stellen überall ein case "Neu" fehlt - ich glaube also, dass dies daher auch fehleranfällig wäre.

    Was ich stattdessen viel lieber hätte, wäre eine enum_java_style-Klasse. Ich stelle mir das wie eine normale enum class vor, die aber die Funktionen to_string und value_of hat - hat so ein bisschen Java-Style enums (also ggf. auch mit weiteren Member-Variablen/Funktionen). Die fehlen mir nämlich in C++ und die würden wahrscheinlich auch die Probleme der anderen Poster hier lösen.



  • @wob

    Schau mal hier Magic enum



  • @wob
    Bei switch (string) geht es eher um from_string und nicht um to_string/value_of.

    Und from_string ist halt fummelig zu implementieren wenn es performant sein soll. Speziell wenn man das static initialization order fiasco vermeiden will/muss.

    Natürlich kann man das alles manuell ausprogrammieren. Genau so wie man manuell Funktoren schreiben kann ohne Lambdas. Macht aber keinen Spass und ist ein Haufen Boilerplate Code der nicht nötig wäre.

    Ein switch (T) das mit allen Typen funktioniert die Hashable und Equality-Comparable sind wäre da schon nett.

    Wie oft man es wirklich braucht ist natürlich die Frage. Wenn man low-level Zeugs schreibt wie performante Parser für textbasierte Formate braucht man es aber schon eher oft.



  • Warum sollte man da eigentlich über eine Hastable gehen?

    switch (my_string) {
      case "Wolf": do_a(); break;
      case "Hustbär": do_b(); break;
      default: do_default();
    }
    

    Hashtable scheint sich doch nur zu lohnen, wenn man richtig viele verschiedene Werte hat - die Hash-Berechnung ist ja schließlich nicht kostenlos und ein == ist häufig recht billig. Erfahrungsgemäß kommt "wenige Fälle" häufiger vor als "viele Fälle". Und wenn du jetzt doch sehr viele cases hast, sodass sich ein Hash ggf. lohnen würde, ist dann nicht die Wahrscheinlichkeit hoch, dass du die case-Werte sowieso irgendwo in einer Datenstruktur zur Verfügung hast und daher gar kein switch/case verwenden würdest?



  • @wob
    Es wäre gut zu wissen wie es in JavaScript umgesetzt ist (zB V8 Engine) oder anderen Sprachen die das erlauben.
    Ist kein 100% Apfel zu Apfel vergleich, aber die haben sie damit auch schon beschäftigt.

    Wär auch ein gutes Thema für ein blogpost mit Performance Tests.


Log in to reply