Увага Mozza314
Ось моделювання ефектів загального std::algorithm
виклику std::swap
та надання користувачеві можливості здійснювати їх обмін у просторі імен std. Оскільки це експеримент, це моделювання використовується 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
) не зупинило його.
Ми з Дейвом обидва члени комітету і працюємо над цією областю стандарту протягом десятиліття (і не завжди узгоджуємо один з одним). Але це питання було врегульовано давно, і ми обидва погоджуємось, як воно було врегульовано. Не зважайте на думку експерта / відповідь Дейва в цій галузі на власну небезпеку.
Ця проблема з'явилася на світ після публікації C ++ 98. Починаючи з 2001 року, ми з Дейвом почали працювати в цій галузі . І це сучасне рішення:
// 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
в простір імен std і змусити його працювати. Але ви повинні пам'ятати , щоб помістити swap
в A
простір імен «S для випадку , коли у вас є шаблон: A<T>
. І оскільки обидва випадки спрацюють, якщо ви помістите swap
в A
простір імен, просто запам'ятати (а також навчити інших) просто робити це одним способом.