สนใจ Mozza314
นี่คือการจำลองเอฟเฟกต์ของการstd::algorithm
โทรทั่วไปstd::swap
และการให้ผู้ใช้ทำการแลกเปลี่ยนในเนมสเปซมาตรฐาน เช่นนี้คือการทดลองจำลองนี้ใช้แทนnamespace exp
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);
}
สำหรับฉันสิ่งนี้พิมพ์ออกมา:
generic exp::swap
หากคอมไพลเลอร์ของคุณพิมพ์สิ่งที่แตกต่างออกไปแสดงว่าการใช้ "การค้นหาสองเฟส" สำหรับเทมเพลตไม่ถูกต้อง
หากคอมไพเลอร์ของคุณสอดคล้อง (กับ C ++ 98/03/11 ใด ๆ ) ก็จะให้ผลลัพธ์เดียวกันกับที่ฉันแสดง และในกรณีนี้สิ่งที่คุณกลัวจะเกิดขึ้น และการใส่swap
เนมสเปซstd
( exp
) ของคุณไม่ได้หยุดยั้งไม่ให้เกิดขึ้น
ฉันและเดฟต่างก็เป็นสมาชิกคณะกรรมการและทำงานด้านมาตรฐานนี้มานานกว่าทศวรรษแล้ว (และไม่ใช่ข้อตกลงซึ่งกันและกันเสมอไป) แต่ปัญหานี้ได้รับการแก้ไขเป็นเวลานานแล้วและเราทั้งสองฝ่ายเห็นพ้องกันว่าจะยุติอย่างไร ไม่สนใจความคิดเห็น / คำตอบของผู้เชี่ยวชาญของ Dave ในพื้นที่นี้ด้วยความเสี่ยงของคุณเอง
ปัญหานี้เกิดขึ้นหลังจากเผยแพร่ C ++ 98 เริ่มต้นประมาณ 2,001 เดฟและฉันเริ่มที่จะทำงานในพื้นที่นี้ และนี่คือทางออกที่ทันสมัย:
// 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);
}
ผลลัพธ์คือ:
swap(A, A)
ปรับปรุง
มีการสังเกตว่า:
namespace exp
{
template <>
void swap(A&, A&)
{
printf("exp::swap(A, A)\n");
}
}
ทำงาน! แล้วทำไมไม่ใช้ล่ะ?
พิจารณากรณีที่คุณA
เป็นแม่แบบคลาส:
// 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);
}
ตอนนี้ใช้ไม่ได้อีกเลย :-(
ดังนั้นคุณสามารถใส่swap
เนมสเปซมาตรฐานและใช้งานได้ แต่คุณจะต้องจำไว้ว่าให้ใส่swap
ในA
namespace 's A<T>
สำหรับกรณีที่เมื่อคุณมีแม่แบบ: และเนื่องจากทั้งสองกรณีจะทำงานถ้าคุณใส่swap
ในA
's namespace ก็เป็นเพียงง่ายต่อการจดจำ (และสอนคนอื่น) ไปเพียงแค่ทำมันว่าวิธีหนึ่ง