Внимание 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имен «s, это просто легче запомнить (и учить других) , чтобы просто сделать это , что так.