swap auch bei Arrays?



  • Ist Folgendes erlaubt und well-formed?

    #include <algorithm>
    
    int main()
    {
    	int a[1] = {4};
    	int b[1] = {6};
    	std::swap(a, b);
    }
    

    Wenn ja, was passiert wenn die beiden Arrays nicht die selbe Größe haben?


  • Mod

    In C++11 hat std::swap eine Überladung für Arrays, die die Elemente einzeln vertauscht. Das geht natürlich nur für gleich große Arrays, ansonsten passt die Überladung nicht und man bekommt einen Compilerfehler. In streng konformem C++98 funktioniert das natürlich auch nicht, sofern die Implementierung diese Überladung nicht als Feature anbietet.



  • Mit C++11 gibt es

    template <typename T, std::size_t N>
    void swap (T (&a) [N], T (&b) [N]);
    

    es sollte also well formed sein.

    Bei unterschiedlicher Größe sollte es einen Compilerfehler geben.


  • Mod

    Es gibt da auch swap_ranges , das kann dann natürlich auf Untermengen angewandt werden.

    swap mit verschiedenen Größen ist doch gar nicht so sinnlos.
    ➡

    template <typename T, std::size_t N1, std::size_t N2>
    void swap (T (&a) [N1], T (&b) [N2])
    {
        std::swap_ranges( a, a + (N1 > N2? N1 : N2), b );
    }
    


  • Arcoth schrieb:

    swap mit verschiedenen Größen ist doch gar nicht so sinnlos.

    Swap mit verschiedenen Grössen ist mindestens verwirrend. Niemand erwartet bei einem harmlosen swap-Aufruf ein teilweises swap.

    Dann doch lieber explizit mit swap_ranges.


  • Mod

    Niemand erwartet bei einem harmlosen swap-Aufruf ein teilweises swap.

    Sondern? Wenn überhaupt, dann ein teilweises swap.



  • Arcoth schrieb:

    Niemand erwartet bei einem harmlosen swap-Aufruf ein teilweises swap.

    Sondern? Wenn überhaupt, dann ein teilweises swap.

    Nein. swap heisst alles oder nichts. swap ist äquivalent zu copy=move(lhs),lhs=move(rhs),rhs=move(copy); bzw in Python-Syntax lhs,rhs = rhs,lhs. Es vertauscht den Inhalt zwei Variablen.

    In diesem Sinne verhält sich dein teilweises swap inkonsistent.


  • Mod

    Ja, wenn man ein Array als ein Objekt betrachtet (welches es auch ist).

    Betrachtet man ein Array als Range, dann könnte ich mir das durchaus vorstellen.
    Wahrscheinlich hast du Recht, und es ist tatsächlich mitunter inkonsistent.



  • dr.sinn schrieb:

    In diesem Sinne verhält sich dein teilweises swap inkonsistent.

    Sehe ich auch so. Der Tausch zweier Objekte, die verschiedene Typen haben, ist im Allgemeinen nicht sinnvoll.



  • Nur so nebenbei, offiziell befindet sich swap in C++11 in <utility>, nicht unbedingt in <algorithm>



  • Flashput schrieb:

    Nur so nebenbei, offiziell befindet sich swap in C++11 in <utility>, nicht unbedingt in <algorithm>

    Es wird sogar nicht einmal vorgeschrieben, dass <algorithm> swap definiert. Wobei es schwer vorstellbar ist, std::iter_swap ohne std::swap umzusetzen ...



  • War im Standard nicht definiert, dass ein Standard-Header nicht unbedingt die swap-Funktion einbindet? Oder so ähnlich?

    In dem Fall kann man iter_swap ja wirklich ohne std::swap umsetzen:

    namespace std
    {
    	template<typename Iter1, typename Iter2>
    	void iter_swap(Iter1 i1, Iter2 i2)
    	{
    		swap(*i1, *i2);
    	}
    }
    

    Wobei sich der Nutzer dann um std::swap kümmern muss.

    Edit:

    17.6.3.2 Swappable requirements schrieb:

    [ Note: It is unspecified whether a library component that has a swappable requirement includes the
    header <utility> to ensure an appropriate evaluation context. —end note ]

    25.3.3 swap [alg.swap] schrieb:

    template<class ForwardIterator1, class ForwardIterator2>
    void iter_swap(ForwardIterator1 a, ForwardIterator2 b);
    5 Effects: swap(*a, *b).
    6 Requires: a and b shall be dereferenceable. *a shall be swappable with (17.6.3.2) *b.


Log in to reply