O C ++ 11 altera o comportamento de chamar explicitamente std :: swap para garantir a troca de ADLs localizadas, como boost :: swap?
Considere esta pergunta o seguinte código:
#include <utility>
namespace ns
{
struct foo
{
foo() : i(0) {}
int i;
private:
foo(const foo&); // not defined,
foo& operator=(const foo&); // non-copyable
};
void swap(foo& lhs, foo& rhs)
{
std::swap(lhs.i, rhs.i);
}
}
template <typename T>
void do_swap(T& lhs, T& rhs); // implementation to be determined
int main()
{
ns::foo a, b;
do_swap(a, b);
}
No C ++ 03, esta implementação dedo_swap
seria considerado "quebrado":
template <typename T>
void do_swap(T& lhs, T& rhs)
{
std::swap(lhs, rhs);
}
Por especificar explicitamentestd::
, proíbens::swap
seja encontrado através da pesquisa dependente de argumento. (Falha na compilação porquestd::swap
tenta copiar umfoo
, o que não é permitido.) Em vez disso, fazemos o seguinte:
template <typename T>
void do_swap(T& lhs, T& rhs)
{
using std::swap; // allow std::swap as a backup if ADL fails to find a swap
swap(lhs, rhs); // unqualified call to swap, allow ADL to operate
}
Agorans::swap
é encontrado estd::swap
, sendo menos especializado, não é usado. É mais feio, mas funciona e é compreensível em retrospectiva.boost::swap
@ encerra isso muito bem para nós (e fornece sobrecargas na matriz
#include <boost/swap.hpp>
template <typename T>
void do_swap(T& lhs, T& rhs)
{
boost::swap(lhs, rhs); // internally does what do_swap did above
}
Questã Minha pergunta é assim: fazstd::swap
assuma o comportamento deboost::swap
em C ++ 11? Se não, por quê?
Para mim, parece óbvio que deveria. Qualquer código quebrado pela mudança provavelmente era bastante instável em primeiro lugar (algoritmos e contêineres, comostd::sort
estd::vector
, foram subespecificados; as implementações foram autorizadas a chamar swap de ADLs ou não indeterminadamente); portanto, a mudança seria para melhor. Além disso,std::swap
agora está definido para matrizes, portanto a alteração não está fora de questã
No entanto, enquanto §17.6.3.2 especifica que todas as chamadas paraswap
na biblioteca padrão deve ser feito semstd::
qualificação (corrigindo o problema com algoritmos e contêineres mencionados acima), ele não toca emstd::swap
em si. Ele ainda fornece exemplos de valores de troca que incluemusing std::swap;
. Da mesma forma §20.2.2 (ondestd::swap
é especificado) não diz uma palavra no AD
Por fim, o GCC não habilita ADL em seusstd::swap
implementação (nem o MSVC, mas isso não está dizendo muito). Então, eu devo estar errado questd::swap
assume o comportamento deboost::swap
, mas não entendo por que a alteração não foi feita. :(E eu não estou sozinho!