string in list vertauschen - verzweiflung...



  • unskilled schrieb:

    http://www.cplusplus.com/reference/

    Ja, die kenne ich schon, ich habe auch unter list eine funktion mit swap gesucht... aber die swap funktion vertauscht "nur" zwei listen...

    Nochmals danke, funktioniert einwandfrei 😃

    Gruß



  • unskilled schrieb:

    Hat sich mittlerweile eigtl was am MSVC-swap geändert, oder wird immernoch jedes mal explizit std::swap verwendet?

    Spielst du auf ADL an? In der Tat, das wäre ein Grund, std::iter_swap() nicht zu verwenden (für das Beispiel von Gustl spielt das natürlich keine Rolle).

    Hm, das ist nicht gut. Ich habe gesehen, dass STL-Algorithmen wie std::random_shuffle() und std::partition() die Funktion std::iter_swap() aufrufen. Könnte bei gewissen Templates etwas ineffizient werden.

    Besser wäre eine Tauschfunktion, welche auf den Namensraum Rücksicht nimmt.

    template <typename T>
    void adl_swap(T& left, T& right)
    {
        using std::swap;
        swap(left, right);
    }
    


  • Nexus schrieb:

    Besser wäre eine Tauschfunktion, welche auf den Namensraum Rücksicht nimmt.

    template <typename T>
    void adl_swap(T& left, T& right)
    {
        using std::swap;
        swap(left, right);
    }
    

    War auch nicht der eigtl Grund, weshalb ich es nicht genutzt habe. ADL ist mir nur erst dann eingefallen^^

    Aber die MS-Leute haben doch vrmtl 999999999x mehr Ahnung als du oder ich - wieso meinst du also, nehmen die keine Rücksicht auf ADL?
    Die Lösung wäre das hier

    template<class _Ty> inline
    	void swap(_Ty& _Left, _Ty& _Right)
    	{	// exchange values stored at _Left and _Right
    	if (&_Left != &_Right)
    		{	// different, worth swapping
    		_Ty _Tmp = _Left;
    
    		_Left = _Right;
    		_Right = _Tmp;
    		}
    	}
    

    durch das

    namespace detail{
      template<typename T>
      void swap(T &lhs, T &rhs)
      {
        if(&lhs == &rhs)
          return;
        T tmp(lhs);
        lhs = rhs;
        rhs = tmp;
      }
    }
    
    template<typename T>
    void swap(T &lhs, T &rhs)
    {
      using detail::swap;
      swap(lhs, rhs);
    }
    

    zu ersetzen...
    Aber eben dummerweise immer nur lokal...
    Wieso steht dort eigtl nen inline davor? ODR wird doch bei templates so und so nicht verletzt und das der MSVC sonst nicht auf die Idee kommt, die Fkt zu inlinen, ist ja nun auch nicht wahr^^

    bb


  • Mod

    unskilled schrieb:

    Aber die MS-Leute haben doch vrmtl 999999999x mehr Ahnung als du oder ich

    Wie es mit deinen Kenntnissen aussieht, weiß ich zwar nicht, trotzdem wage ich zu bezweifeln, dass diese Aussage so zutreffend ist.
    Und selbst wenn es stimmt, bedeutet das nicht, dass keine Fehler gemacht würden.
    Nebenbei ist iter_swap nicht genau genug spezifiziert.

    unskilled schrieb:

    namespace detail{
      template<typename T>
      void swap(T &lhs, T &rhs)
      {
        if(&lhs == &rhs)
          return;
        T tmp(lhs);
        lhs = rhs;
        rhs = tmp;
      }
    }
    

    Eigentlich ist der Test &lhr==&rhs völlig überflüssig und kostet nur unnötig Performance. Schließlich wird swap mit sich selbst nur selten auftreten, die Kosten für das if bezahlt man aber immer. Insbesondere wenn die Kopierkosten gering sind (z.B. bei int), ist diese Prüfung Unfug.



  • camper schrieb:

    Nebenbei ist iter_swap nicht genau genug spezifiziert.

    imho aber ein wenig krümelkackerei - klar hätte man hinschreiben können: works like swap(*lhs, *rhs) aber ich glaube nicht, dass es irgend eine vernünftige standard-lib-implementierung gibt, die das nicht auch so tut...

    camper schrieb:

    Eigentlich ist der Test &lhr==&rhs völlig überflüssig und kostet nur unnötig Performance. Schließlich wird swap mit sich selbst nur selten auftreten, die Kosten für das if bezahlt man aber immer. Insbesondere wenn die Kopierkosten gering sind (z.B. bei int), ist diese Prüfung Unfug.

    ok - überzeugt^^

    bb



  • namespace detail{ 
      template<typename T> 
      void swap(T &lhs, T &rhs) 
      { 
        T tmp(lhs); 
        lhs = rhs; 
        rhs = tmp; 
      } 
    } 
    
    template<typename T> 
    void swap(T &lhs, T &rhs) 
    { 
      using detail::swap; 
      swap(lhs, rhs); 
    }
    

    Super Idee, die ich da wieder hatte xD
    Ratet mal was passiert, wenn es kein spez. swap gibt : D
    Kann man den ambigious call iwie verhindern(also das std::swap ausschließen?^^)

    bb


  • Mod

    unskilled schrieb:

    Kann man den ambigious call iwie verhindern(also das std::swap ausschließen?^^)

    namespace detail{
      template<typename T>
      void swap(T &lhs, T &rhs)
      {
        T tmp(lhs);
        lhs = rhs;
        rhs = tmp;
      }
    
      template<typename T>
      void swap_impl(T &lhs, T &rhs)
      {
        swap(lhs, rhs);
      }
    }
    template<typename T>
    void swap(T &lhs, T &rhs)
    {
      detail::swap_impl(lhs, rhs);
    }
    

    führt aber immer noch zu Mehrdeutigkeit, wenn std zufällig mal ein assozierter Namensraum ist, ohne dass gleichzeitig eine entsprechende Spezialisierung existiert.



  • hmm.. ok - scheint also nicht wirklich elegant zu gehen-.-

    camper schrieb:

    wenn std zufällig mal ein assozierter Namensraum ist

    das versteh ich nicht ganz... hast du evtl nen bsp. oder ne andere erklärung?

    ty, bb


  • Mod

    #include <algorithm>
    #include <vector>
    template <typename> struct foo {};
    int main()
    {
        static foo<std::vector<int> > a, b;
        std::swap( a, b ); // mehrdeutig, Kandidaten in std::detail::swap_impl:  std::swap und std::detail::swap
                           // lösbar, wenn man sämtliche Deklarationen in std nach std::detail verschiebt und in std nur using-Deklarationen benutzt
                           // (abgesehen von swap)
        std::vector<int> c, d;
        std::swap( c, d ); // ok, da mit speziellerem template in std überladen
    }
    


  • hmm... schade^^
    wäre direkt mal nen feature request wert - ich glaub zumindest nicht, dass es in der 2010er geändert ist...
    ich hab zumindest keine lust, jedes mal auch noch (illegalerweise) std::swap zu überladen...
    mir würde höchstens noch einfallen, mit enable_if/disable_if nen anderes swap anzubieten, wenn T ne Fkt swap(T&) besitzt...
    oder würde da noch iwas dagegen sprechen (außer das es an und für sich schon blödsinnig ist, ne standard-lib zu verändern)

    bb


Anmelden zum Antworten