Chú ý Mozza314
Dưới đây là một mô phỏng về các hiệu ứng của một std::algorithm
cuộc gọi chung std::swap
và để người dùng cung cấp trao đổi của họ trong không gian tên std. Vì đây là một thử nghiệm, mô phỏng này sử dụng namespace exp
thay vì 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);
}
Đối với tôi điều này in ra:
generic exp::swap
Nếu trình biên dịch của bạn in ra một cái gì đó khác nhau thì nó không thực hiện chính xác "tra cứu hai pha" cho các mẫu.
Nếu trình biên dịch của bạn tuân thủ (với bất kỳ C ++ 98/03/11 nào), thì nó sẽ cho cùng một đầu ra mà tôi hiển thị. Và trong trường hợp đó chính xác những gì bạn sợ sẽ xảy ra, sẽ xảy ra. Và việc đặt bạn swap
vào không gian tên std
( exp
) không ngăn điều đó xảy ra.
Dave và tôi đều là thành viên ủy ban và đã làm việc trong lĩnh vực tiêu chuẩn này trong một thập kỷ (và không phải lúc nào cũng đồng ý với nhau). Nhưng vấn đề này đã được giải quyết trong một thời gian dài và cả hai chúng tôi đều đồng ý về cách giải quyết nó. Bỏ qua ý kiến / câu trả lời của chuyên gia Dave trong lĩnh vực này trong tình trạng nguy hiểm của riêng bạn.
Vấn đề này được đưa ra ánh sáng sau khi C ++ 98 được xuất bản. Bắt đầu khoảng năm 2001 Dave và tôi bắt đầu làm việc trong lĩnh vực này . Và đây là giải pháp hiện đại:
// 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);
}
Đầu ra là:
swap(A, A)
Cập nhật
Một quan sát đã được thực hiện rằng:
namespace exp
{
template <>
void swap(A&, A&)
{
printf("exp::swap(A, A)\n");
}
}
làm! Vậy tại sao không sử dụng?
Hãy xem xét trường hợp của bạn A
là một mẫu lớp:
// 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);
}
Bây giờ nó không hoạt động trở lại. :-(
Vì vậy, bạn có thể đặt swap
trong không gian tên std và làm cho nó hoạt động. Nhưng bạn sẽ cần phải nhớ để đặt swap
ở A
's namespace cho trường hợp khi bạn có một mẫu: A<T>
. Và vì cả hai trường hợp sẽ hoạt động nếu bạn đặt swap
trong A
không gian tên, nên việc nhớ (và dạy người khác) sẽ dễ dàng hơn khi làm theo cách đó.