- adalah tepat penggunaan dari
swap
. Tulis dengan cara ini ketika Anda menulis kode "library" dan ingin mengaktifkan ADL (pencarian yang bergantung pada argumen) swap
. Juga, ini tidak ada hubungannya dengan SFINAE.
template<class T>
void foo(T& lhs, T& rhs) {
using std::swap;
swap(lhs, rhs);
}
- Adalah cara yang tepat untuk menyediakan
swap
fungsi untuk kelas Anda.
namespace Foo {
class Bar{};
void swap(Bar& lhs, Bar& rhs) {
}
}
Jika swap
sekarang digunakan seperti yang ditunjukkan pada 1), fungsi Anda akan ditemukan. Juga, Anda dapat menjadikan fungsi itu sebagai teman jika Anda benar-benar membutuhkannya, atau menyediakan anggota swap
yang dipanggil dengan fungsi gratis:
class Bar{
public:
friend void swap(Bar& lhs, Bar& rhs) {
}
};
class Bar{
public:
void swap(Bar& other) {
}
};
void swap(Bar& lhs, Bar& rhs) {
lhs.swap(rhs);
}
...
- Yang Anda maksud adalah spesialisasi eksplisit. Partial masih merupakan sesuatu yang lain dan juga tidak mungkin untuk fungsi, hanya struct / class. Dengan demikian, karena Anda tidak dapat mengkhususkan diri
std::swap
untuk kelas template, Anda harus menyediakan fungsi gratis di namespace Anda. Bukan hal yang buruk, jika boleh saya katakan. Sekarang, spesialisasi eksplisit juga dimungkinkan, tetapi umumnya Anda tidak ingin mengkhususkan template fungsi :
namespace std
{
template<>
void swap<Bar>(Bar& lhs, Bar& rhs) noexcept {
}
}
- Tidak, karena 1) berbeda dari 2) dan 3). Juga, memiliki 2) dan 3) akan menyebabkan selalu 2) memilih, karena lebih cocok.
using std::swap;
tidak mengaktifkan ADL, ini hanya memungkinkan kompiler untuk mencari lokasistd::swap
jika ADL tidak menemukan kelebihan beban yang sesuai.Untuk menjawab EDIT, di mana kelas mungkin kelas template, Anda tidak perlu spesialisasi sama sekali. pertimbangkan kelas seperti ini:
template <class T> struct vec3 { T x,y,z; };
Anda dapat mendefinisikan kelas-kelas seperti:
vec3<float> a; vec3<double> b; vec3<int> c;
jika Anda ingin dapat membuat satu fungsi untuk mengimplementasikan semua 3 swap (bukan kelas contoh ini menjaminnya) Anda melakukan seperti yang dikatakan Xeo di (2) ... tanpa spesialisasi tetapi cukup buat 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 template swap harus ditempatkan di namespace yang sama dengan kelas yang Anda coba tukar. metode berikut akan menemukan dan menggunakan swap itu meskipun Anda tidak mereferensikan namespace itu menggunakan ADL:
using std::swap; swap(a,b);
sumber
Tampaknya (2) ( berdiri bebas
swap
di namespace yang sama di mana kelas yang ditentukan pengguna dideklarasikan ) adalah satu-satunya cara yang diizinkan untuk menyediakanswap
kelas yang ditentukan pengguna, karena menambahkan deklarasi ke namespacestd
umumnya merupakan perilaku yang tidak ditentukan. Memperluas namespace std (cppreference.com) :Dan
swap
tidak dilambangkan sebagai salah satu pengecualian itu. Jadi menambahkanswap
kelebihan Anda sendiri kestd
namespace adalah perilaku yang tidak ditentukan.Juga dikatakan bahwa pustaka standar menggunakan panggilan yang tidak memenuhi syarat ke
swap
fungsi untuk memanggil yang ditentukanswap
pengguna untuk kelas pengguna jika ditentukan penggunaswap
tersebut disediakan.Dapat ditukar (cppreference.com) :
swap (www.cplusplus.com) :
Namun perhatikan bahwa secara langsung menggunakan
std::swap
fungsi untuk kelas yang ditentukan pengguna akan memanggil versi generik,std::swap
bukan yang ditentukan penggunaswap
:my::object a, b; std::swap(a, b); // calls std::swap, not my::swap
Jadi direkomendasikan untuk memanggil
swap
fungsi dalam kode pengguna dengan cara yang sama seperti yang dilakukan di pustaka standar:my::object a, b; using std::swap; swap(a, b); // calls my::swap if it is defined, or std::swap if it is not.
sumber