std::hash fuer QString (QT) in unordered_map



  • Hi zusammen

    ich habe in meiner Klasse eine unordered_map ( als Member ) fuer die ich die Hashfunktionen als Lambdas definieren möchte.

    private:
    auto eq  = [](const QString &key1, const QString &key2){return key1 == key2; };
    auto hs  = [](const QString &key) { return std::hash<std::string>()( key.toStdString() ); };
    std::unordered_map<QString, std::shared_ptr<MultiRow>,  decltype(hs), decltype(eq)> Data;
    };
    

    Leider akzeptiert der Compiler das ganz und gar nicht.

    Fehler: non-static data member declared 'auto'

    Ich habs auch mit static und constexpr. Fehlanzeige.

    Geht das mit Lambdas bei einer Map als Member überhaupt, und wenn ja wie?
    Ich bin doch sicher nicht der erste, der für eine externe String-Klasse ( in dem Fall QTs QString ) die Hash-Funktionen definieren will, oder?

    Dank & Gruß

    Tobi


  • Mod

    Die direkte Art und Weise, die mir spontan einfällt, ist, einfach kein auto zu nutzen. Ein lambda ist ein Funktionsobjekt, also passt vom Typ her std::function<passende argumente>. Beispielsweise:

    #include <functional>
    
    class X
    {
     private:
      std::function<void(int)> foo = [](int a){return a+5;};
    };
    


  • Sieht gut aus 🙂 Compiler ist erstmal zufrieden. Ich gehe davon aus, dass die Map dann auch funzt.

    Danke dir!



  • Du könntest natürlich auch QHash verwenden. Das sollte mit QString ja direkt funktionieren.


  • Mod

    SeppJ schrieb:

    Die direkte Art und Weise, die mir spontan einfällt, ist, einfach kein auto zu nutzen. Ein lambda ist ein Funktionsobjekt, also passt vom Typ her std::function<passende argumente>. Beispielsweise:

    #include <functional>
    
    class X
    {
     private:
      std::function<void(int)> foo = [](int a){return a+5;};
    };
    

    Funktionszeiger sind aus der Mode?



  • Da bin ich auch schon drüber gestolpert. auto funktioniert da nicht, den Typ einenes Lambdas kann man auch nicht direkt angeben, std::function will man wegen des Overheads eventuell auch nicht haben. Nicht sehr schön gelöst.


  • Mod

    Ich habs auch mit static und constexpr. Fehlanzeige.

    Äh, mit static gehts. Du musst natürlich die Hashfunktion im Konstruktor übergeben da closure Typen keine Defaultkonstruktoren haben, aber ansonsten sollte das problemlos kompilieren.



  • @TNA: mit welcher Art von Overhead habe ich bei std::function zu rechnen?

    @Arcoth: wie würde deine Lösung mit Funktionszeigern aussehen?

    Meine Lösung habe ich jetzt erstmal so:

    std::function<bool(const QString &,const QString &)> eq  = [](const QString &key1, const QString &key2){return key1 == key2; };
    std::function<bool(const QString &)> hs  = [](const QString &key) { return std::hash<std::string>()( key.toStdString() ); };
    std::unordered_map<QString, std::shared_ptr<MultiRow>,  decltype(hs), decltype(eq)> Data;
    


  • Jemand ne Idee?



  • Na, so:

    private:
      static constexpr auto eq  = [](const QString &key1, const QString &key2){return key1 == key2; };
      static constexpr auto hs  = [](const QString &key) { return std::hash<std::string>()(key.toStdString() ); };
      std::unordered_map<QString, std::shared_ptr<MultiRow>,  decltype(hs), decltype(eq)> Data;
    };
    

Anmelden zum Antworten