Pertanyaan bagaimana cara menyediakan fungsi swap untuk kelas saya?


Apa cara yang tepat untuk mengaktifkan saya swap dalam algoritma STL?

1) Anggota swap. Apakah std::swap gunakan trik SFINAE untuk menggunakan anggota swap.

2) Berdiri bebas swap di ruang nama yang sama.

3) Spesialisasi parsial dari std::swap.

4) Semua hal di atas.

Terima kasih.

EDIT: Sepertinya saya tidak mengatakan pertanyaan saya dengan jelas. Pada dasarnya, saya memiliki kelas template dan saya perlu algos STL untuk menggunakan metode swap (efisien) yang saya tulis untuk kelas itu.


75
2018-06-17 02:51


asal


Jawaban:


1) adalah yang tepat menggunakan dari swap. Tuliskan cara ini ketika Anda menulis kode "pustaka" dan ingin mengaktifkan ADL (pencarian tergantung argumen) swap. Juga, ini tidak ada hubungannya dengan 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) Apakah cara yang tepat untuk menyediakan swap berfungsi untuk kelas Anda.

namespace Foo{

class Bar{}; // dummy

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

}

Jika swap sekarang digunakan seperti yang ditunjukkan pada 1), fungsi Anda akan ditemukan. Juga, Anda dapat menjadikannya berfungsi sebagai teman jika Anda benar-benar perlu, atau memberikan anggota swap yang disebut dengan fungsi gratis:

// 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) Maksud Anda spesialisasi eksplisit. Sebagian masih sesuatu yang lain dan juga tidak mungkin untuk fungsi, hanya structs / class. Dengan demikian, karena Anda tidak dapat berspesialisasi std::swap untuk kelas template, Anda memiliki untuk menyediakan fungsi gratis di ruang nama Anda. Bukan hal yang buruk, jika boleh saya katakan demikian. Sekarang, spesialisasi eksplisit juga mungkin, tetapi umumnya Anda tidak ingin mengkhususkan template fungsi:

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

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

}

4) Tidak, karena 1) berbeda dari 2) dan 3). Juga, memiliki keduanya 2) dan 3) akan menyebabkan selalu memiliki 2) dipilih, karena lebih pas.


84
2018-06-17 02:54



Untuk menjawab EDIT, di mana kelas mungkin kelas template, Anda tidak memerlukan spesialisasi sama sekali. pertimbangkan kelas seperti ini:

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

Anda dapat menentukan kelas seperti:

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

jika Anda ingin dapat membuat satu fungsi untuk mengimplementasikan semua 3 swap (bukan bahwa kelas contoh ini menjamin) Anda melakukan seperti yang dikatakan Xeo di (2) ... tanpa spesialisasi tetapi hanya membuat fungsi template biasa:

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

Fungsi templat swap harus ditempatkan di ruang nama yang sama dengan kelas yang Anda coba tukar. metode berikut akan menemukan dan menggunakan swap itu meskipun Anda tidak mereferensikan namespace menggunakan ADL:

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

1
2017-12-15 01:28