2011-01-24 8 views
20

Durante un poco de práctica de C++, estaba tratando de aprender y adoptar el modismo de copiado después de esta exhaustiva explicación sobre esta pregunta: the Copy-Swap Idiom.¿Qué significa `using std :: swap` dentro del cuerpo de una implementación de método de clase?

Pero he encontrado algo de código que nunca había visto: using std::swap; // allow ADL en este ejemplo

class dumb_array 
{ 
public: 
    // ... 

    void swap(dumb_array& pOther) // nothrow 
    { 
     using std::swap; // allow ADL /* <===== THE LINE I DONT UNDERSTAND */ 

     swap(mSize, pOther.mSize); // with the internal members swapped, 
     swap(mArray, pOther.mArray); // *this and pOther are effectively swapped 
    } 
}; 
  1. ¿qué quiere decir using std::swap; en el interior del cuerpo de una función aplicación?
  2. ¿Qué significa ADL?
+1

[La respuesta de MSalter] (http://stackoverflow.com/a/4782809/464581) es en mi humilde opinión la mejor respuesta más completa, ya que explica sobre ADL (que es la razón completa para hacer el 'uso' aquí) . Creo que deberías seleccionar eso como una solución. –

Respuesta

52

Este mecanismo se utiliza normalmente en el código de plantilla, es decir, template <typename Value> class Foo.

Ahora la pregunta es qué intercambio usar. std::swap<Value> funcionará, pero podría no ser ideal. Hay una buena posibilidad de que exista una mejor sobrecarga de swap para el tipo Value, pero ¿en qué espacio de nombres sería eso? Es casi seguro que no está en std:: (ya que eso es ilegal), pero muy probablemente en el espacio de nombres de Value. Probablemente, pero lejos de ser cierto.

En ese caso, swap(myValue, anotherValue) le ofrecerá el "mejor" cambio posible. Argumento Dependent Lookup encontrará cualquier intercambio en el espacio de nombres de donde proviene el Value. De lo contrario, se iniciará la directiva using y se creará una instancia y se usará std::swap<Value>.

En su código, mSize es probablemente un tipo integral, y mArray un puntero. Ninguno de los dos tiene un espacio de nombres asociado, y std::swap tiene una certeza del 99.9% óptima para ellos de todos modos. Por lo tanto, la declaración using std::swap; parece inútil aquí.

+5

Creo que es bastante legal proporcionar especializaciones de funciones estándar en el espacio de nombres 'std'. §17.4.3.1/1 "Un programa puede agregar especializaciones de plantilla para cualquier plantilla de biblioteca estándar al espacio de nombres std. Tal especialización (completa o parcial) de una plantilla de biblioteca estándar da como resultado un comportamiento indefinido a menos que la declaración dependa de un nombre de usuario definido vinculación externa y, a menos que la especialización cumpla con los requisitos de la biblioteca estándar para la plantilla original "Dicho esto, no es común implementar especializaciones' swap' en el espacio de nombres 'std'. –

+7

@dribeas: de hecho es legal especializar 'std :: swap', y si tiene dudas acerca de sus usuarios, probablemente debería especializar' std :: swap' * y * proporcionar un 'swap' en su propio espacio de nombres para que lo pueda encontrar ADL. Pero hay límites para especializar 'std :: swap', el asesino es que no se puede * parcialmente * especializar, porque es una plantilla de función, y por lo tanto, si usted ha escrito una plantilla de clase (como un contenedor nuevo) , no puedes especializar 'std :: swap' para eso, y por lo tanto debes tomar la ruta ADL. MSalters tiene razón en lo que dice, sin embargo: no se puede sobrecargar 'std :: swap', solo se especializan. –

10

La palabra clave using tiene efecto de ámbito.

Esto significa que std::swap se puede consultar como swap durante el alcance de la palabra clave using.

+16

y creo que ADL en este contexto solo significa "búsqueda dependiente del argumento". Eso permite que el código use "swap" con o sin una función de intercambio local definida. Si no existe uno local, entonces se usa std :: swap – vmpstr

+3

@vmpstr: Si lo pones como una respuesta separada, obtienes 10 reputación solo porque la voto. – Benoit

+4

Esta es una respuesta inútil para ser honesto. No explica la interacción de 'using std :: swap' y ADL. La respuesta de MSalters debería ser la aceptada. –

-2

Respuesta corta

using std::swap; // allow ADL /* <===== THE LINE I DONT UNDERSTAND */ 

necesaria para evitar la llamada recursiva a la permuta miembro. El intercambio de miembros desactiva ADL.

Cuestiones relacionadas