Attenzione Mozza314
Ecco una simulazione degli effetti di una std::algorithm
chiamata generica std::swap
e che l'utente fornisce il proprio scambio nello spazio dei nomi std. Poiché si tratta di un esperimento, questa simulazione utilizza namespace exp
invece di 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);
}
Per me questo stampa:
generic exp::swap
Se il tuo compilatore stampa qualcosa di diverso, non sta implementando correttamente la "ricerca in due fasi" per i modelli.
Se il tuo compilatore è conforme (a uno qualsiasi di C ++ 98/03/11), allora darà lo stesso output che mostro. E in quel caso accade esattamente quello che temi che accada. E mettere il tuo swap
in namespace std
( exp
) non ha impedito che accadesse.
Dave ed io siamo entrambi membri del comitato e lavoriamo in quest'area dello standard da un decennio (e non sempre in accordo l'uno con l'altro). Ma la questione è stata risolta da molto tempo e siamo entrambi d'accordo su come è stata risolta. Ignora l'opinione / risposta degli esperti di Dave in questo settore a tuo rischio e pericolo.
Questo problema è emerso dopo la pubblicazione di C ++ 98. A partire dal 2001, Dave e io abbiamo iniziato a lavorare in quest'area . E questa è la soluzione moderna:
// 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);
}
L'output è:
swap(A, A)
Aggiornare
È stata fatta un'osservazione che:
namespace exp
{
template <>
void swap(A&, A&)
{
printf("exp::swap(A, A)\n");
}
}
lavori! Allora perché non usarlo?
Considera il caso in cui il tuo A
è un modello di classe:
// 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);
}
Ora non funziona più. :-(
Quindi potresti inserire lo swap
spazio dei nomi std e farlo funzionare. Ma è necessario ricordarsi di mettere swap
in A
's spazio dei nomi per il caso in cui si dispone di un modello: A<T>
. E dal momento che entrambi i casi, funzionano se si mette swap
in A
's spazio dei nomi, è solo più facile da ricordare (e ad altri insegnano) per farlo solo che un modo.