jak zapewnić funkcję swap dla mojej klasy?

Jak poprawnie włączyć moje swap w algorytmach STL?

1) członek swap. Czy std::swap używa sztuczki SFINAE, aby użyć członka swap.

2) wolnostojący swap w tej samej przestrzeni nazw.

3) częściowa specjalizacja std::swap.

[[6]}4) wszystkie powyższe. Dziękuję.

EDIT: wygląda na to, że nie wyraziłem jasno swojego pytania. Zasadniczo, mam klasę szablonu i potrzebuję STL algos, aby użyć (wydajnej) metody swap, którą napisałem dla tej klasy.

Author: pic11, 2011-06-17

2 answers

1) jest właściwym użyciem z swap. Zapisz to w ten sposób, gdy piszesz kod "library" i chcesz włączyć ADL (wyszukiwanie zależne od argumentów) na swap. Ponadto nie ma to nic wspólnego z SFINAE.

// 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) jest właściwym sposobem zapewnienia swap funkcji dla twojej klasy.

namespace Foo{

class Bar{}; // dummy

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

}

Jeśli swap jest teraz używany, jak pokazano w 1), twoja funkcja zostanie znaleziona. Ponadto, możesz uczynić tę funkcję przyjacielem, jeśli koniecznie musisz, lub podać członka swap, który jest wywoływany przez funkcja swobodna:

// 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) masz na myśli wyraźną specjalizację. Partial jest jeszcze czymś innym i nie jest możliwe dla funkcji, tylko structs / classes. Jako takie, ponieważ nie możesz specjalizować się std::swap w klasach szablonów, musisz zapewnić wolną funkcję w swojej przestrzeni nazw. Nie jest źle, jeśli mogę tak powiedzieć. Obecnie możliwa jest również wyraźna specjalizacja, ale ogólnie nie chcesz specjalizować szablonu funkcji :

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

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

}

4) Nie, ponieważ 1) różni się od 2) i 3). Ponadto posiadanie zarówno 2), jak i 3) doprowadzi do zawsze posiadania 2) picked, ponieważ lepiej pasuje.

 87
Author: Xeo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-12 13:21:33

Aby odpowiedzieć na edycję, gdzie klasy mogą być klasami szablonowymi, w ogóle nie potrzebujesz specjalizacji. rozważ klasę taką jak Ta:

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

Można zdefiniować klasy takie jak:

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

Jeśli chcesz być w stanie stworzyć jedną funkcję do zaimplementowania wszystkich 3 swapów (Nie żeby ta przykładowa Klasa tego gwarantowała), robisz tak jak Xeo powiedział w (2)... bez specjalizacji, ale wystarczy zrobić zwykłą funkcję szablonu:

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);
}

Funkcja szablonu swap powinna znajdować się w tym samym przestrzeń nazw jako klasa, którą próbujesz zamienić. poniższa metoda znajdzie i użyje tego swapu, nawet jeśli nie odwołujesz się do tej przestrzeni nazw za pomocą ADL:

using std::swap;
swap(a,b);
 1
Author: Ben,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-15 02:08:19