Frage Wie stelle ich eine Swap-Funktion für meine Klasse zur Verfügung?


Was ist der richtige Weg, um meine swap in STL-Algorithmen?

1) Mitglied swap. Tut std::swap Verwenden Sie den SFINAE-Trick, um das Mitglied zu verwenden swap.

2) Freistehend swap im selben Namespace.

3) Teilspezialisierung von std::swap.

4) Alles oben genannte.

Vielen Dank.

EDIT: Sieht so aus, als hätte ich meine Frage nicht klar formuliert. Im Grunde habe ich eine Template-Klasse und brauche STL-Algos, um die (effiziente) Swap-Methode zu verwenden, die ich für diese Klasse geschrieben habe.


75
2018-06-17 02:51


Ursprung


Antworten:


1) ist das Richtige benutzen von swap. Schreiben Sie es so, wenn Sie "Bibliothekscode" schreiben und ADL (argumentabhängige Suche) aktivieren möchten swap. Das hat auch nichts mit SFINAE zu tun.

// some algorithm in your code
template<class T>
void foo(T& lhs, T& rhs){
  using std::swap; // enable 'std::swap' to be found
                   // if no other 'swap' is found through ADL
  // some code ...
  swap(lhs, rhs); // unqualified call, uses ADL and finds a fitting 'swap'
                  // or falls back on 'std::swap'
  // more code ...
}

2) Ist der richtige Weg, um eine swap Funktion für Ihre Klasse.

namespace Foo{

class Bar{}; // dummy

void swap(Bar& lhs, Bar& rhs){
  // ...
}

}

Ob swap wird jetzt wie in 1) verwendet, Ihre Funktion wird gefunden. Außerdem können Sie diese Funktion zu einem Freund machen, wenn Sie es unbedingt benötigen oder ein Mitglied bereitstellen müssen swap das nennt man die freie Funktion:

// version 1
class Bar{
public:
  friend void swap(Bar& lhs, Bar& rhs){
    // ....
  }
};

// version 2
class Bar{
public:
  void swap(Bar& other){
    // ...
  }
};

void swap(Bar& lhs, Bar& rhs){
  lhs.swap(rhs);
}

3) Sie meinen eine explizite Spezialisierung. Teilweise ist noch etwas anderes und auch nicht möglich für Funktionen, nur Strukturen / Klassen. Daher kann man sich nicht spezialisieren std::swap für Vorlagenklassen, Sie haben um eine freie Funktion in Ihrem Namensraum zur Verfügung zu stellen. Keine schlechte Sache, wenn ich das sagen darf. Nun ist auch eine explizite Spezialisierung möglich, aber generell Sie möchten keine Funktionsvorlage spezialisieren:

namespace std
{  // only allowed to extend namespace std with specializations

template<> // specialization
void swap<Bar>(Bar& lhs, Bar& rhs){
  // ...
}

}

4) Nein, wie 1) unterscheidet sich von 2) und 3). Auch wenn 2) und 3) vorhanden sind, wird immer 2) ausgewählt, weil es besser passt.


84
2018-06-17 02:54



Um die EDIT zu beantworten, wo die Klassen Template-Klassen sein können, brauchen Sie überhaupt keine Spezialisierung. Betrachte eine Klasse wie diese:

template <class T>
struct vec3
{
    T x,y,z;
};

Sie können Klassen definieren wie:

vec3<float> a;
vec3<double> b;
vec3<int> c;

Wenn Sie eine Funktion zum Implementieren aller 3 Swaps erstellen möchten (nicht, dass diese Beispielklasse dies rechtfertigt), tun Sie genau wie Xeo in (2) ... ohne Spezialisierung, aber machen Sie einfach eine reguläre Template-Funktion:

template <class T>
void swap(vec3<T> &a, vec3<T> &b)
{
    using std::swap;
    swap(a.x,b.x);
    swap(a.y,b.y);
    swap(a.z,b.z);
}

Die Auslagerungsvorlagenfunktion sollte sich im selben Namespace befinden wie die Klasse, die Sie austauschen möchten. Die folgende Methode findet und verwendet diesen Swap, obwohl Sie diesen Namespace nicht mithilfe von ADL referenzieren:

using std::swap;
swap(a,b);

1
2017-12-15 01:28