sirve que programacion para nombres namespace guardar espacios espacio escribir dev con como c++ namespaces operator-keyword

c++ - para - que es using namespace std en programacion



Espacios de nombres y resoluciĆ³n del operador (4)

Como Test está dentro del espacio de nombres B la compilación ve al operador en ese espacio de nombres y señala que no tiene una firma coincidente. También intenta encontrar el operador en el espacio de nombres A que contiene la clase pero tampoco la puede encontrar allí. Debido a que ya existe dicho operador (con la firma incorrecta) en el espacio de nombres B , no funcionará e intentará encontrar uno en el alcance global.

La razón por la que no busca la global es más o menos la siguiente. Primero voy a citar el estándar y luego trato de explicarlo.

Desde 3.4 / 1:

... La búsqueda de nombres puede asociar más de una declaración con un nombre si encuentra que el nombre es un nombre de función; se dice que las declaraciones forman un conjunto de funciones sobrecargadas (13.1). La resolución de sobrecarga (13.3) tiene lugar después de que la búsqueda de nombres ha tenido éxito.

Mientras leo esto, cuando el compilador intenta encontrar una función (que sus operadores se encuentran en este contexto), primero intenta buscar nombres para encontrar la función primero. Luego, a continuación, intenta elegir la función correcta del conjunto de sobrecargas.

Ahora de 3.4.1 / 6:

Un nombre utilizado en la definición de una función (26) que es miembro del espacio de nombres N (donde, solo para el propósito de la exposición, N podría representar el alcance global) debe declararse antes de su uso en el bloque en el que se utiliza o en uno de sus bloques adjuntos (6.3) o, se declarará antes de su uso en el espacio de nombres N o, si N es un espacio de nombres anidado, se declarará antes de su uso en uno de los espacios de nombres adjuntos de N.

Vamos a romper esto. Está utilizando el operator<< en una función de nivel de espacio de nombres así que esta sección se aplica. Intentará encontrar ese operador usando la precedencia en el descrito arriba. Su operador no está declarado en el bloque actual ni en los bloques adjuntos (esto se refiere a {} anidado dentro de su función). Sin embargo, la siguiente parte coincide con "... se declarará antes de su uso en el espacio de nombres N ...". De hecho, hay un operator<< en el espacio de nombre actual ( B ) por lo que agrega ese operador a su lista de coincidencias. No hay más coincidencias en B , y como el alcance del mismo nombre se considera la mejor cercanía posible, no buscará en ningún otro ámbito.

La razón por la que funciona cuando coloca el operador en el espacio de nombres A es que dado que el elemento que se está imprimiendo es miembro de A , ese espacio de nombres se considera realmente porque está incluido en los espacios de nombres de la expresión. Como se considera el espacio de nombres A , encuentra la coincidencia adecuada en ese espacio de nombres y se compila correctamente.

Ahora que tiene una lista de posibles operadores, intenta hacer una resolución de sobrecarga en ellos. Lamentablemente, el encontrado en el espacio de nombres B es el único que considera y no coincide con los argumentos requeridos.

En general, debe tener los operadores de inserción en el mismo espacio de nombres que la clase en la que opera.

Estoy usando una biblioteca que define operadores de flujo de salida (operador <<) en el espacio de nombres global. En mi propio espacio de nombres, siempre estaba declarando esos operadores en el espacio de nombres global, y nunca tuve problemas con ellos. Pero ahora, por varias razones, necesito declarar esos operadores en mi propio espacio de nombres, y de repente, parece que el compilador ya no puede encontrar los operadores declarados en la biblioteca.

Aquí hay un ejemplo simple que ilustra mi problema:

#include <iostream> namespace A { struct MyClass {}; } std::ostream & operator<<( std::ostream & os, const A::MyClass & ) { os << "namespace A"; return os; } namespace B { struct MyClass {}; std::ostream & operator<<( std::ostream & os, const B::MyClass & ) { os << "namespace B"; return os; } } namespace B { void Test() { std::cout << A::MyClass() << std::endl; std::cout << B::MyClass() << std::endl; } } int main() { B::Test(); return 1; }

Estoy teniendo el siguiente error:

error: no match for ‘operator<<’ in ‘std::cout << A::MyClass()’

Tenga en cuenta que si ambos operadores están dentro de los espacios de nombres, o alternativamente si están ambos en el espacio de nombres global, el código se compila y ejecuta correctamente.

Realmente me gustaría entender qué está pasando y también cuál es la "buena práctica" para definir esos operadores con espacios de nombres.

¡Gracias!


El problema ha sido explicado en la respuesta por @Mark B. Lo siguiente resuelve el problema. En el espacio de nombres donde desea utilizar el operator<< global operator<< , escriba el siguiente código:

using ::operator<<;

En el ejemplo del código de OP, esa línea de código iría a la ubicación a lo largo del otro código que declara / define el operator<< para el namespace B de namespace B :

namespace B { struct MyClass {}; std::ostream & operator<<( std::ostream & os, const B::MyClass & ) { os << "namespace B"; return os; } using ::operator<<; }


Es porque su primer operator<<() se define fuera del espacio de nombres A.


Mi respuesta es muy similar a las otras, pero en particular, el compilador está tratando de encontrar A :: operator << () porque está operando en algo en el espacio de nombres A. Si desea invocar el que está fuera del espacio de nombres, puede llamarlo de manera explícita mediante el uso de

::operator<<(std::cout, A::MyClass();

Para un uso sintáctico más fluido, colóquelo en el espacio de nombres.