Perhatian Mozza314
Berikut adalah simulasi dari efek std::algorithm
pemanggilan generik std::swap
, dan meminta pengguna menyediakan swap mereka di namespace std. Karena ini adalah sebuah eksperimen, simulasi ini menggunakan namespace exp
bukan namespace std
.
// simulate <algorithm>
#include <cstdio>
namespace exp
{
template <class T>
void
swap(T& x, T& y)
{
printf("generic exp::swap\n");
T tmp = x;
x = y;
y = tmp;
}
template <class T>
void algorithm(T* begin, T* end)
{
if (end-begin >= 2)
exp::swap(begin[0], begin[1]);
}
}
// simulate user code which includes <algorithm>
struct A
{
};
namespace exp
{
void swap(A&, A&)
{
printf("exp::swap(A, A)\n");
}
}
// exercise simulation
int main()
{
A a[2];
exp::algorithm(a, a+2);
}
Bagi saya ini cetakannya:
generic exp::swap
Jika kompilator Anda mencetak sesuatu yang berbeda maka kompilator tidak menerapkan "pencarian dua fase" untuk template dengan benar.
Jika kompiler Anda sesuai (ke salah satu dari C ++ 98/03/11), maka itu akan memberikan keluaran yang sama yang saya tunjukkan. Dan dalam kasus seperti itu, apa yang Anda takuti akan terjadi, benar-benar terjadi. Dan memasukkan Anda swap
ke dalam namespace std
( exp
) tidak menghentikannya terjadi.
Dave dan saya adalah anggota komite dan telah mengerjakan bidang standar ini selama satu dekade (dan tidak selalu sesuai satu sama lain). Tetapi masalah ini telah diselesaikan untuk waktu yang lama, dan kami berdua sepakat tentang cara menyelesaikannya. Abaikan pendapat / jawaban ahli Dave di bidang ini atas risiko Anda sendiri.
Masalah ini terungkap setelah C ++ 98 diterbitkan. Mulai sekitar 2001 Dave dan saya mulai mengerjakan bidang ini . Dan inilah solusi modern:
// simulate <algorithm>
#include <cstdio>
namespace exp
{
template <class T>
void
swap(T& x, T& y)
{
printf("generic exp::swap\n");
T tmp = x;
x = y;
y = tmp;
}
template <class T>
void algorithm(T* begin, T* end)
{
if (end-begin >= 2)
swap(begin[0], begin[1]);
}
}
// simulate user code which includes <algorithm>
struct A
{
};
void swap(A&, A&)
{
printf("swap(A, A)\n");
}
// exercise simulation
int main()
{
A a[2];
exp::algorithm(a, a+2);
}
Outputnya adalah:
swap(A, A)
Memperbarui
Pengamatan telah dilakukan bahwa:
namespace exp
{
template <>
void swap(A&, A&)
{
printf("exp::swap(A, A)\n");
}
}
berhasil! Jadi mengapa tidak menggunakan itu?
Pertimbangkan kasus Anda A
adalah template kelas:
// simulate user code which includes <algorithm>
template <class T>
struct A
{
};
namespace exp
{
template <class T>
void swap(A<T>&, A<T>&)
{
printf("exp::swap(A, A)\n");
}
}
// exercise simulation
int main()
{
A<int> a[2];
exp::algorithm(a, a+2);
}
Sekarang tidak berfungsi lagi. :-(
Jadi Anda bisa memasukkan swap
namespace std dan membuatnya berfungsi. Tapi Anda harus ingat untuk menempatkan swap
diA
's namespace untuk kasus ketika Anda memiliki template: A<T>
. Dan karena kedua kasus akan bekerja jika Anda meletakkan swap
di A
's namespace, itu hanya lebih mudah untuk mengingat (dan mengajar orang lain) untuk hanya melakukannya bahwa salah satu cara.